diff --git a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DeviceListActivity.java b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DeviceListActivity.java
index fd2429a..c7804e0 100644
--- a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DeviceListActivity.java
+++ b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/DeviceListActivity.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.examples;
@@ -41,6 +42,7 @@ import android.widget.TextView;
import android.widget.TwoLineListItem;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
+import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.HexDump;
@@ -80,19 +82,8 @@ public class DeviceListActivity extends Activity {
};
- /** Simple container for a UsbDevice and its driver. */
- private static class DeviceEntry {
- public UsbDevice device;
- public UsbSerialDriver driver;
-
- DeviceEntry(UsbDevice device, UsbSerialDriver driver) {
- this.device = device;
- this.driver = driver;
- }
- }
-
- private List mEntries = new ArrayList();
- private ArrayAdapter mAdapter;
+ private List mEntries = new ArrayList();
+ private ArrayAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -104,7 +95,8 @@ public class DeviceListActivity extends Activity {
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
- mAdapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_2, mEntries) {
+ mAdapter = new ArrayAdapter(this,
+ android.R.layout.simple_expandable_list_item_2, mEntries) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final TwoLineListItem row;
@@ -116,14 +108,16 @@ public class DeviceListActivity extends Activity {
row = (TwoLineListItem) convertView;
}
- final DeviceEntry entry = mEntries.get(position);
+ final UsbSerialPort port = mEntries.get(position);
+ final UsbSerialDriver driver = port.getDriver();
+ final UsbDevice device = driver.getDevice();
+
final String title = String.format("Vendor %s Product %s",
- HexDump.toHexString((short) entry.device.getVendorId()),
- HexDump.toHexString((short) entry.device.getProductId()));
+ HexDump.toHexString((short) device.getVendorId()),
+ HexDump.toHexString((short) device.getProductId()));
row.getText1().setText(title);
- final String subtitle = entry.driver != null ?
- entry.driver.getClass().getSimpleName() : "No Driver";
+ final String subtitle = driver.getClass().getSimpleName();
row.getText2().setText(subtitle);
return row;
@@ -141,14 +135,8 @@ public class DeviceListActivity extends Activity {
return;
}
- final DeviceEntry entry = mEntries.get(position);
- final UsbSerialDriver driver = entry.driver;
- if (driver == null) {
- Log.d(TAG, "No driver.");
- return;
- }
-
- showConsoleActivity(driver);
+ final UsbSerialPort port = mEntries.get(position);
+ showConsoleActivity(port);
}
});
}
@@ -168,31 +156,28 @@ public class DeviceListActivity extends Activity {
private void refreshDeviceList() {
showProgressBar();
- new AsyncTask>() {
+ new AsyncTask>() {
@Override
- protected List doInBackground(Void... params) {
+ protected List doInBackground(Void... params) {
Log.d(TAG, "Refreshing device list ...");
SystemClock.sleep(1000);
- final List result = new ArrayList();
- for (final UsbDevice device : mUsbManager.getDeviceList().values()) {
- final List drivers =
- UsbSerialProber.probeSingleDevice(mUsbManager, device);
- Log.d(TAG, "Found usb device: " + device);
- if (drivers.isEmpty()) {
- Log.d(TAG, " - No UsbSerialDriver available.");
- result.add(new DeviceEntry(device, null));
- } else {
- for (UsbSerialDriver driver : drivers) {
- Log.d(TAG, " + " + driver);
- result.add(new DeviceEntry(device, driver));
- }
- }
+
+ final List drivers =
+ UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);
+
+ final List result = new ArrayList();
+ for (final UsbSerialDriver driver : drivers) {
+ final List ports = driver.getPorts();
+ Log.d(TAG, String.format("+ %s: %s port%s",
+ driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s"));
+ result.addAll(ports);
}
+
return result;
}
@Override
- protected void onPostExecute(List result) {
+ protected void onPostExecute(List result) {
mEntries.clear();
mEntries.addAll(result);
mAdapter.notifyDataSetChanged();
@@ -214,8 +199,8 @@ public class DeviceListActivity extends Activity {
mProgressBar.setVisibility(View.INVISIBLE);
}
- private void showConsoleActivity(UsbSerialDriver driver) {
- SerialConsoleActivity.show(this, driver);
+ private void showConsoleActivity(UsbSerialPort port) {
+ SerialConsoleActivity.show(this, port);
}
}
diff --git a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/SerialConsoleActivity.java b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/SerialConsoleActivity.java
index 7ccb406..d30ff51 100644
--- a/UsbSerialExamples/src/com/hoho/android/usbserial/examples/SerialConsoleActivity.java
+++ b/UsbSerialExamples/src/com/hoho/android/usbserial/examples/SerialConsoleActivity.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.examples;
@@ -23,12 +24,14 @@ package com.hoho.android.usbserial.examples;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.hardware.usb.UsbDeviceConnection;
+import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.ScrollView;
import android.widget.TextView;
-import com.hoho.android.usbserial.driver.UsbSerialDriver;
+import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.util.HexDump;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
@@ -37,7 +40,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
- * Monitors a single {@link UsbSerialDriver} instance, showing all data
+ * Monitors a single {@link UsbSerialPort} instance, showing all data
* received.
*
* @author mike wakerly (opensource@hoho.com)
@@ -48,7 +51,7 @@ public class SerialConsoleActivity extends Activity {
/**
* Driver instance, passed in statically via
- * {@link #show(Context, UsbSerialDriver)}.
+ * {@link #show(Context, UsbSerialPort)}.
*
*
* This is a devious hack; it'd be cleaner to re-create the driver using
@@ -56,7 +59,7 @@ public class SerialConsoleActivity extends Activity {
* can get away with it because both activities will run in the same
* process, and this is a simple demo.
*/
- private static UsbSerialDriver sDriver = null;
+ private static UsbSerialPort sPort = null;
private TextView mTitleTextView;
private TextView mDumpTextView;
@@ -98,13 +101,13 @@ public class SerialConsoleActivity extends Activity {
protected void onPause() {
super.onPause();
stopIoManager();
- if (sDriver != null) {
+ if (sPort != null) {
try {
- sDriver.close();
+ sPort.close();
} catch (IOException e) {
// Ignore.
}
- sDriver = null;
+ sPort = null;
}
finish();
}
@@ -112,25 +115,33 @@ public class SerialConsoleActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
- Log.d(TAG, "Resumed, sDriver=" + sDriver);
- if (sDriver == null) {
+ Log.d(TAG, "Resumed, port=" + sPort);
+ if (sPort == null) {
mTitleTextView.setText("No serial device.");
} else {
+ final UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
+
+ UsbDeviceConnection connection = usbManager.openDevice(sPort.getDriver().getDevice());
+ if (connection == null) {
+ mTitleTextView.setText("Opening device failed");
+ return;
+ }
+
try {
- sDriver.open();
- sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
+ sPort.open(connection);
+ sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
} catch (IOException e) {
Log.e(TAG, "Error setting up device: " + e.getMessage(), e);
mTitleTextView.setText("Error opening device: " + e.getMessage());
try {
- sDriver.close();
+ sPort.close();
} catch (IOException e2) {
// Ignore.
}
- sDriver = null;
+ sPort = null;
return;
}
- mTitleTextView.setText("Serial device: " + sDriver.getClass().getSimpleName());
+ mTitleTextView.setText("Serial device: " + sPort.getClass().getSimpleName());
}
onDeviceStateChange();
}
@@ -144,9 +155,9 @@ public class SerialConsoleActivity extends Activity {
}
private void startIoManager() {
- if (sDriver != null) {
+ if (sPort != null) {
Log.i(TAG, "Starting io manager ..");
- mSerialIoManager = new SerialInputOutputManager(sDriver, mListener);
+ mSerialIoManager = new SerialInputOutputManager(sPort, mListener);
mExecutor.submit(mSerialIoManager);
}
}
@@ -169,8 +180,8 @@ public class SerialConsoleActivity extends Activity {
* @param context
* @param driver
*/
- static void show(Context context, UsbSerialDriver driver) {
- sDriver = driver;
+ static void show(Context context, UsbSerialPort port) {
+ sPort = port;
final Intent intent = new Intent(context, SerialConsoleActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
index 34fa14a..3e764ab 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CdcAcmSerialDriver.java
@@ -1,3 +1,24 @@
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
+ */
+
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbConstants;
@@ -8,7 +29,9 @@ import android.hardware.usb.UsbInterface;
import android.util.Log;
import java.io.IOException;
+import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -19,201 +42,243 @@ import java.util.Map;
* href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf">Universal
* Serial Bus Class Definitions for Communication Devices, v1.1
*/
-public class CdcAcmSerialDriver extends CommonUsbSerialDriver {
+public class CdcAcmSerialDriver implements UsbSerialDriver {
private final String TAG = CdcAcmSerialDriver.class.getSimpleName();
- private UsbInterface mControlInterface;
- private UsbInterface mDataInterface;
+ private final UsbDevice mDevice;
+ private final UsbSerialPort mPort;
- private UsbEndpoint mControlEndpoint;
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
-
- 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);
+ public CdcAcmSerialDriver(UsbDevice device) {
+ mDevice = device;
+ mPort = new CdcAdcmSerialPort(device);
}
@Override
- public void open() throws IOException {
- Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
+ public UsbDevice getDevice() {
+ return mDevice;
+ }
- Log.d(TAG, "Claiming control interface.");
- mControlInterface = mDevice.getInterface(0);
- Log.d(TAG, "Control iface=" + mControlInterface);
- // class should be USB_CLASS_COMM
+ @Override
+ public List getPorts() {
+ return Collections.singletonList(mPort);
+ }
- if (!mConnection.claimInterface(mControlInterface, true)) {
- throw new IOException("Could not claim control interface.");
+ class CdcAdcmSerialPort extends CommonUsbSerialPort {
+
+ private UsbInterface mControlInterface;
+ private UsbInterface mDataInterface;
+
+ private UsbEndpoint mControlEndpoint;
+ private UsbEndpoint mReadEndpoint;
+ private UsbEndpoint mWriteEndpoint;
+
+ 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 CdcAdcmSerialPort(UsbDevice device) {
+ super(device);
}
- 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.");
+ @Override
+ public UsbSerialDriver getDriver() {
+ return CdcAcmSerialDriver.this;
}
- mReadEndpoint = mDataInterface.getEndpoint(1);
- Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection());
- mWriteEndpoint = mDataInterface.getEndpoint(0);
- Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection());
- }
- 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;
+ @Override
+ public void open(UsbDeviceConnection connection) throws IOException {
+ if (mConnection != null) {
+ throw new IOException("Already open");
+ }
+
+ mConnection = connection;
+ boolean opened = false;
+ try {
+ Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
+ 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());
+ opened = true;
+ } finally {
+ if (!opened) {
+ mConnection = null;
+ }
}
- 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;
+ 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);
+ }
- while (offset < src.length) {
- final int writeLength;
- final int amtWritten;
+ @Override
+ public void close() throws IOException {
+ if (mConnection == null) {
+ throw new IOException("Already closed");
+ }
+ mConnection.close();
+ mConnection = null;
+ }
- synchronized (mWriteBufferLock) {
- final byte[] writeBuffer;
+ @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;
+ }
- 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;
+ @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);
}
- amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
- timeoutMillis);
+ Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
+ offset += amtWritten;
}
- if (amtWritten <= 0) {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length=" + src.length);
+ return offset;
+ }
+
+ @Override
+ public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
+ byte stopBitsByte;
+ switch (stopBits) {
+ case STOPBITS_1: stopBitsByte = 0; break;
+ case STOPBITS_1_5: stopBitsByte = 1; break;
+ case STOPBITS_2: stopBitsByte = 2; break;
+ default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
}
- Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
- offset += amtWritten;
- }
- return offset;
- }
+ 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);
+ }
- @Override
- public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
- byte stopBitsByte;
- switch (stopBits) {
- case STOPBITS_1: stopBitsByte = 0; break;
- case STOPBITS_1_5: stopBitsByte = 1; break;
- case STOPBITS_2: stopBitsByte = 2; break;
- default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
+ 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);
}
- 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);
+ @Override
+ public boolean getCD() throws IOException {
+ return false; // TODO
}
- 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 getCTS() throws IOException {
+ return false; // TODO
+ }
- @Override
- public boolean getCD() throws IOException {
- return false; // TODO
- }
+ @Override
+ public boolean getDSR() throws IOException {
+ return false; // TODO
+ }
- @Override
- public boolean getCTS() throws IOException {
- return false; // TODO
- }
+ @Override
+ public boolean getDTR() throws IOException {
+ return mDtr;
+ }
- @Override
- public boolean getDSR() throws IOException {
- return false; // TODO
- }
+ @Override
+ public void setDTR(boolean value) throws IOException {
+ mDtr = value;
+ setDtrRts();
+ }
- @Override
- public boolean getDTR() throws IOException {
- return mDtr;
- }
+ @Override
+ public boolean getRI() throws IOException {
+ return false; // TODO
+ }
- @Override
- public void setDTR(boolean value) throws IOException {
- mDtr = value;
- setDtrRts();
- }
+ @Override
+ public boolean getRTS() throws IOException {
+ return mRts;
+ }
- @Override
- public boolean getRI() throws IOException {
- return false; // TODO
- }
+ @Override
+ public void setRTS(boolean value) throws IOException {
+ mRts = value;
+ setDtrRts();
+ }
- @Override
- public boolean getRTS() throws IOException {
- return mRts;
- }
+ private void setDtrRts() {
+ int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
+ sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
+ }
- @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 getSupportedDevices() {
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialPort.java
similarity index 90%
rename from UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialDriver.java
rename to UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialPort.java
index 7c61704..d8a9e1f 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CommonUsbSerialPort.java
@@ -1,4 +1,5 @@
-/* Copyright 2013 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.driver;
@@ -30,13 +31,15 @@ import java.io.IOException;
*
* @author mike wakerly (opensource@hoho.com)
*/
-abstract class CommonUsbSerialDriver implements UsbSerialDriver {
+abstract class CommonUsbSerialPort implements UsbSerialPort {
public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024;
protected final UsbDevice mDevice;
- protected final UsbDeviceConnection mConnection;
+
+ // non-null when open()
+ protected UsbDeviceConnection mConnection = null;
protected final Object mReadBufferLock = new Object();
protected final Object mWriteBufferLock = new Object();
@@ -47,9 +50,8 @@ abstract class CommonUsbSerialDriver implements UsbSerialDriver {
/** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */
protected byte[] mWriteBuffer;
- public CommonUsbSerialDriver(UsbDevice device, UsbDeviceConnection connection) {
+ public CommonUsbSerialPort(UsbDevice device) {
mDevice = device;
- mConnection = connection;
mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE];
mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
@@ -95,7 +97,7 @@ abstract class CommonUsbSerialDriver implements UsbSerialDriver {
}
@Override
- public abstract void open() throws IOException;
+ public abstract void open(UsbDeviceConnection connection) throws IOException;
@Override
public abstract void close() throws IOException;
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java
index 7e9118b..a427a18 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/Cp2102SerialDriver.java
@@ -1,8 +1,25 @@
-package com.hoho.android.usbserial.driver;
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
+ */
-import java.io.IOException;
-import java.util.LinkedHashMap;
-import java.util.Map;
+package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
@@ -11,273 +28,323 @@ import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.util.Log;
-public class Cp2102SerialDriver extends CommonUsbSerialDriver {
- private static final String TAG = Cp2102SerialDriver.class.getSimpleName();
-
- private static final int DEFAULT_BAUD_RATE = 9600;
-
- private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
-
- /*
- * Configuration Request Types
- */
- private static final int REQTYPE_HOST_TO_DEVICE = 0x41;
-
- /*
- * Configuration Request Codes
- */
- private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
- private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
- private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
- private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
- private static final int SILABSER_SET_BAUDRATE = 0x1E;
- private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12;
-
- private static final int FLUSH_READ_CODE = 0x0a;
- private static final int FLUSH_WRITE_CODE = 0x05;
-
- /*
- * SILABSER_IFC_ENABLE_REQUEST_CODE
- */
- private static final int UART_ENABLE = 0x0001;
- private static final int UART_DISABLE = 0x0000;
-
- /*
- * SILABSER_SET_BAUDDIV_REQUEST_CODE
- */
- private static final int BAUD_RATE_GEN_FREQ = 0x384000;
-
- /*
- * SILABSER_SET_MHS_REQUEST_CODE
- */
- private static final int MCR_DTR = 0x0001;
- private static final int MCR_RTS = 0x0002;
- private static final int MCR_ALL = 0x0003;
-
- private static final int CONTROL_WRITE_DTR = 0x0100;
- private static final int CONTROL_WRITE_RTS = 0x0200;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
-
- public Cp2102SerialDriver(UsbDevice device, UsbDeviceConnection connection) {
- super(device, connection);
- }
-
- private int setConfigSingle(int request, int value) {
- return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
- 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+public class Cp2102SerialDriver implements UsbSerialDriver {
+
+ private static final String TAG = Cp2102SerialDriver.class.getSimpleName();
+
+ private final UsbDevice mDevice;
+ private final UsbSerialPort mPort;
+
+ public Cp2102SerialDriver(UsbDevice device) {
+ mDevice = device;
+ mPort = new Cp2102SerialPort(mDevice);
}
@Override
- public void open() throws IOException {
- boolean opened = false;
- try {
- for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
- UsbInterface usbIface = mDevice.getInterface(i);
- if (mConnection.claimInterface(usbIface, true)) {
- Log.d(TAG, "claimInterface " + i + " SUCCESS");
- } else {
- Log.d(TAG, "claimInterface " + i + " FAIL");
- }
- }
-
- UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
- for (int i = 0; i < dataIface.getEndpointCount(); i++) {
- UsbEndpoint ep = dataIface.getEndpoint(i);
- if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
- if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
- mReadEndpoint = ep;
+ public UsbDevice getDevice() {
+ return mDevice;
+ }
+
+ @Override
+ public List getPorts() {
+ return Collections.singletonList(mPort);
+ }
+
+ class Cp2102SerialPort extends CommonUsbSerialPort {
+
+ private static final int DEFAULT_BAUD_RATE = 9600;
+
+ private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
+
+ /*
+ * Configuration Request Types
+ */
+ private static final int REQTYPE_HOST_TO_DEVICE = 0x41;
+
+ /*
+ * Configuration Request Codes
+ */
+ private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
+ private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
+ private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
+ private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
+ private static final int SILABSER_SET_BAUDRATE = 0x1E;
+ private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12;
+
+ private static final int FLUSH_READ_CODE = 0x0a;
+ private static final int FLUSH_WRITE_CODE = 0x05;
+
+ /*
+ * SILABSER_IFC_ENABLE_REQUEST_CODE
+ */
+ private static final int UART_ENABLE = 0x0001;
+ private static final int UART_DISABLE = 0x0000;
+
+ /*
+ * SILABSER_SET_BAUDDIV_REQUEST_CODE
+ */
+ private static final int BAUD_RATE_GEN_FREQ = 0x384000;
+
+ /*
+ * SILABSER_SET_MHS_REQUEST_CODE
+ */
+ private static final int MCR_DTR = 0x0001;
+ private static final int MCR_RTS = 0x0002;
+ private static final int MCR_ALL = 0x0003;
+
+ private static final int CONTROL_WRITE_DTR = 0x0100;
+ private static final int CONTROL_WRITE_RTS = 0x0200;
+
+ private UsbEndpoint mReadEndpoint;
+ private UsbEndpoint mWriteEndpoint;
+
+ public Cp2102SerialPort(UsbDevice device) {
+ super(device);
+ }
+
+ @Override
+ public UsbSerialDriver getDriver() {
+ return Cp2102SerialDriver.this;
+ }
+
+ private int setConfigSingle(int request, int value) {
+ return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
+ 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ }
+
+ @Override
+ public void open(UsbDeviceConnection connection) throws IOException {
+ if (mConnection != null) {
+ throw new IOException("Already opened.");
+ }
+
+ mConnection = connection;
+ boolean opened = false;
+ try {
+ for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
+ UsbInterface usbIface = mDevice.getInterface(i);
+ if (mConnection.claimInterface(usbIface, true)) {
+ Log.d(TAG, "claimInterface " + i + " SUCCESS");
} else {
- mWriteEndpoint = ep;
+ Log.d(TAG, "claimInterface " + i + " FAIL");
+ }
+ }
+
+ UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
+ for (int i = 0; i < dataIface.getEndpointCount(); i++) {
+ UsbEndpoint ep = dataIface.getEndpoint(i);
+ if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
+ if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
+ mReadEndpoint = ep;
+ } else {
+ mWriteEndpoint = ep;
+ }
+ }
+ }
+
+ setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE);
+ setConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS);
+ setConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);
+ // setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY);
+ opened = true;
+ } finally {
+ if (!opened) {
+ try {
+ close();
+ } catch (IOException e) {
+ // Ignore IOExceptions during close()
}
}
}
-
- setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE);
- setConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS);
- setConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);
-// setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY);
- opened = true;
- } finally {
- if (!opened) {
- close();
- }
- }
- }
-
- @Override
- public void close() throws IOException {
- setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
- 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 {
- int offset = 0;
+ @Override
+ public void close() throws IOException {
+ if (mConnection == null) {
+ throw new IOException("Already closed");
+ }
+ try {
+ setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
+ mConnection.close();
+ } finally {
+ mConnection = null;
+ }
+ }
- while (offset < src.length) {
- final int writeLength;
- final int amtWritten;
+ @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;
+ }
- synchronized (mWriteBufferLock) {
- final byte[] writeBuffer;
+ @Override
+ public int write(byte[] src, int timeoutMillis) throws IOException {
+ int offset = 0;
- 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;
+ 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);
}
- amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
- timeoutMillis);
+ Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
+ offset += amtWritten;
}
- if (amtWritten <= 0) {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length=" + src.length);
+ return offset;
+ }
+
+ private void setBaudRate(int baudRate) throws IOException {
+ byte[] data = new byte[] {
+ (byte) ( baudRate & 0xff),
+ (byte) ((baudRate >> 8 ) & 0xff),
+ (byte) ((baudRate >> 16) & 0xff),
+ (byte) ((baudRate >> 24) & 0xff)
+ };
+ int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
+ 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
+ if (ret < 0) {
+ throw new IOException("Error setting baud rate.");
}
-
- Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
- offset += amtWritten;
- }
- return offset;
- }
-
- private void setBaudRate(int baudRate) throws IOException {
- byte[] data = new byte[] {
- (byte) ( baudRate & 0xff),
- (byte) ((baudRate >> 8 ) & 0xff),
- (byte) ((baudRate >> 16) & 0xff),
- (byte) ((baudRate >> 24) & 0xff)
- };
- int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
- 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
- if (ret < 0) {
- throw new IOException("Error setting baud rate.");
- }
- }
-
- @Override
- public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
- throws IOException {
- setBaudRate(baudRate);
-
- int configDataBits = 0;
- switch (dataBits) {
- case DATABITS_5:
- configDataBits |= 0x0500;
- break;
- case DATABITS_6:
- configDataBits |= 0x0600;
- break;
- case DATABITS_7:
- configDataBits |= 0x0700;
- break;
- case DATABITS_8:
- configDataBits |= 0x0800;
- break;
- default:
- configDataBits |= 0x0800;
- break;
- }
- setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
-
- int configParityBits = 0; // PARITY_NONE
- switch (parity) {
- case PARITY_ODD:
- configParityBits |= 0x0010;
- break;
- case PARITY_EVEN:
- configParityBits |= 0x0020;
- break;
- }
- setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configParityBits);
-
- int configStopBits = 0;
- switch (stopBits) {
- case STOPBITS_1:
- configStopBits |= 0;
- break;
- case STOPBITS_2:
- configStopBits |= 2;
- break;
- }
- setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configStopBits);
- }
-
- @Override
- public boolean getCD() throws IOException {
- return false;
- }
-
- @Override
- public boolean getCTS() throws IOException {
- return false;
- }
-
- @Override
- public boolean getDSR() throws IOException {
- return false;
- }
-
- @Override
- public boolean getDTR() throws IOException {
- return true;
- }
-
- @Override
- public void setDTR(boolean value) throws IOException {
- }
-
- @Override
- public boolean getRI() throws IOException {
- return false;
- }
-
- @Override
- public boolean getRTS() throws IOException {
- return true;
- }
-
- @Override
- public boolean purgeHwBuffers(boolean purgeReadBuffers,
- boolean purgeWriteBuffers) throws IOException {
- int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
- | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
-
- if (value != 0) {
- setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value);
}
- return true;
+ @Override
+ public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
+ throws IOException {
+ setBaudRate(baudRate);
+
+ int configDataBits = 0;
+ switch (dataBits) {
+ case DATABITS_5:
+ configDataBits |= 0x0500;
+ break;
+ case DATABITS_6:
+ configDataBits |= 0x0600;
+ break;
+ case DATABITS_7:
+ configDataBits |= 0x0700;
+ break;
+ case DATABITS_8:
+ configDataBits |= 0x0800;
+ break;
+ default:
+ configDataBits |= 0x0800;
+ break;
+ }
+ setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
+
+ int configParityBits = 0; // PARITY_NONE
+ switch (parity) {
+ case PARITY_ODD:
+ configParityBits |= 0x0010;
+ break;
+ case PARITY_EVEN:
+ configParityBits |= 0x0020;
+ break;
+ }
+ setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configParityBits);
+
+ int configStopBits = 0;
+ switch (stopBits) {
+ case STOPBITS_1:
+ configStopBits |= 0;
+ break;
+ case STOPBITS_2:
+ configStopBits |= 2;
+ break;
+ }
+ setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configStopBits);
+ }
+
+ @Override
+ public boolean getCD() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getCTS() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getDSR() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getDTR() throws IOException {
+ return true;
+ }
+
+ @Override
+ public void setDTR(boolean value) throws IOException {
+ }
+
+ @Override
+ public boolean getRI() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getRTS() throws IOException {
+ return true;
+ }
+
+ @Override
+ public void setRTS(boolean value) throws IOException {
+ }
+
+ @Override
+ public boolean purgeHwBuffers(boolean purgeReadBuffers,
+ boolean purgeWriteBuffers) throws IOException {
+ int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
+ | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
+
+ if (value != 0) {
+ setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value);
+ }
+
+ return true;
+ }
+
}
- @Override
- public void setRTS(boolean value) throws IOException {
- }
-
public static Map getSupportedDevices() {
final Map supportedDevices = new LinkedHashMap();
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILAB),
@@ -287,5 +354,4 @@ public class Cp2102SerialDriver extends CommonUsbSerialDriver {
return supportedDevices;
}
-
}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
index caaa4ec..7aad732 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/FtdiSerialDriver.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.driver;
@@ -31,14 +32,16 @@ import com.hoho.android.usbserial.util.HexDump;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
/**
- * A {@link CommonUsbSerialDriver} implementation for a variety of FTDI devices
+ * A {@link CommonUsbSerialPort} implementation for a variety of FTDI devices
*
- * This driver is based on
- * libftdi, and is
+ * This driver is based on libftdi, and is
* copyright and subject to the following terms:
*
*
@@ -58,9 +61,11 @@ import java.util.Map;
* unsupported devices. Devices listed as "supported" support the following
* features:
*
- * - Read and write of serial data (see {@link #read(byte[], int)} and
- * {@link #write(byte[], int)}.
- *
- Setting baud rate (see {@link #setBaudRate(int)}).
+ *
- Read and write of serial data (see
+ * {@link CommonUsbSerialPort#read(byte[], int)} and
+ * {@link CommonUsbSerialPort#write(byte[], int)}.
+ * - Setting serial line parameters (see
+ * {@link CommonUsbSerialPort#setParameters(int, int, int, int)}.
*
*
*
@@ -82,73 +87,15 @@ import java.util.Map;
*
*
* @author mike wakerly (opensource@hoho.com)
- * @see USB Serial
- * for Android project page
+ * @see USB Serial
+ * for Android project page
* @see FTDI Homepage
* @see libftdi
*/
-public class FtdiSerialDriver extends CommonUsbSerialDriver {
+public class FtdiSerialDriver implements UsbSerialDriver {
- public static final int USB_TYPE_STANDARD = 0x00 << 5;
- public static final int USB_TYPE_CLASS = 0x01 << 5;
- public static final int USB_TYPE_VENDOR = 0x02 << 5;
- public static final int USB_TYPE_RESERVED = 0x03 << 5;
-
- public static final int USB_RECIP_DEVICE = 0x00;
- public static final int USB_RECIP_INTERFACE = 0x01;
- public static final int USB_RECIP_ENDPOINT = 0x02;
- public static final int USB_RECIP_OTHER = 0x03;
-
- public static final int USB_ENDPOINT_IN = 0x80;
- public static final int USB_ENDPOINT_OUT = 0x00;
-
- public static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
- public static final int USB_READ_TIMEOUT_MILLIS = 5000;
-
- // From ftdi.h
- /**
- * Reset the port.
- */
- private static final int SIO_RESET_REQUEST = 0;
-
- /**
- * Set the modem control register.
- */
- private static final int SIO_MODEM_CTRL_REQUEST = 1;
-
- /**
- * Set flow control register.
- */
- private static final int SIO_SET_FLOW_CTRL_REQUEST = 2;
-
- /**
- * Set baud rate.
- */
- private static final int SIO_SET_BAUD_RATE_REQUEST = 3;
-
- /**
- * Set the data characteristics of the port.
- */
- private static final int SIO_SET_DATA_REQUEST = 4;
-
- private static final int SIO_RESET_SIO = 0;
- private static final int SIO_RESET_PURGE_RX = 1;
- private static final int SIO_RESET_PURGE_TX = 2;
-
- public static final int FTDI_DEVICE_OUT_REQTYPE =
- UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT;
-
- public static final int FTDI_DEVICE_IN_REQTYPE =
- UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN;
-
- /**
- * Length of the modem status header, transmitted with every read.
- */
- private static final int MODEM_STATUS_HEADER_LENGTH = 2;
-
- private final String TAG = FtdiSerialDriver.class.getSimpleName();
-
- private DeviceType mType;
+ private final UsbDevice mDevice;
+ private final UsbSerialPort mPort;
/**
* FTDI chip types.
@@ -157,382 +104,467 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver {
TYPE_BM, TYPE_AM, TYPE_2232C, TYPE_R, TYPE_2232H, TYPE_4232H;
}
- private int mInterface = 0; /* INTERFACE_ANY */
-
- private int mMaxPacketSize = 64; // TODO(mikey): detect
-
- /**
- * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads
- * since it gives no indication of number of bytes read. Set this to
- * {@code true} on platforms where it is fixed.
- */
- private static final boolean ENABLE_ASYNC_READS = false;
-
- /**
- * Filter FTDI status bytes from buffer
- * @param src The source buffer (which contains status bytes)
- * @param dest The destination buffer to write the status bytes into (can be src)
- * @param totalBytesRead Number of bytes read to src
- * @param maxPacketSize The USB endpoint max packet size
- * @return The number of payload bytes
- */
- private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) {
- final int packetsCount = totalBytesRead / maxPacketSize + 1;
- for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) {
- final int count = (packetIdx == (packetsCount - 1))
- ? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH
- : maxPacketSize - MODEM_STATUS_HEADER_LENGTH;
- if (count > 0) {
- System.arraycopy(src,
- packetIdx * maxPacketSize + MODEM_STATUS_HEADER_LENGTH,
- dest,
- packetIdx * (maxPacketSize - MODEM_STATUS_HEADER_LENGTH),
- count);
- }
- }
-
- return totalBytesRead - (packetsCount * 2);
+ public FtdiSerialDriver(UsbDevice device) {
+ mDevice = device;
+ mPort = new FtdiSerialPort(mDevice);
}
-
- /**
- * Constructor.
- *
- * @param usbDevice the {@link UsbDevice} to use
- * @param usbConnection the {@link UsbDeviceConnection} to use
- * @throws UsbSerialRuntimeException if the given device is incompatible
- * with this driver
- */
- public FtdiSerialDriver(UsbDevice usbDevice, UsbDeviceConnection usbConnection) {
- super(usbDevice, usbConnection);
- mType = null;
- }
-
- public void reset() throws IOException {
- int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0) {
- throw new IOException("Reset failed: result=" + result);
- }
-
- // TODO(mikey): autodetect.
- mType = DeviceType.TYPE_R;
+ @Override
+ public UsbDevice getDevice() {
+ return mDevice;
}
@Override
- public void open() throws IOException {
- boolean opened = false;
- try {
- for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
- if (mConnection.claimInterface(mDevice.getInterface(i), true)) {
- Log.d(TAG, "claimInterface " + i + " SUCCESS");
- } else {
- throw new IOException("Error claiming interface " + i);
+ public List getPorts() {
+ return Collections.singletonList(mPort);
+ }
+
+ private class FtdiSerialPort extends CommonUsbSerialPort {
+
+ public static final int USB_TYPE_STANDARD = 0x00 << 5;
+ public static final int USB_TYPE_CLASS = 0x00 << 5;
+ public static final int USB_TYPE_VENDOR = 0x00 << 5;
+ public static final int USB_TYPE_RESERVED = 0x00 << 5;
+
+ public static final int USB_RECIP_DEVICE = 0x00;
+ public static final int USB_RECIP_INTERFACE = 0x01;
+ public static final int USB_RECIP_ENDPOINT = 0x02;
+ public static final int USB_RECIP_OTHER = 0x03;
+
+ public static final int USB_ENDPOINT_IN = 0x80;
+ public static final int USB_ENDPOINT_OUT = 0x00;
+
+ public static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
+ public static final int USB_READ_TIMEOUT_MILLIS = 5000;
+
+ // From ftdi.h
+ /**
+ * Reset the port.
+ */
+ private static final int SIO_RESET_REQUEST = 0;
+
+ /**
+ * Set the modem control register.
+ */
+ private static final int SIO_MODEM_CTRL_REQUEST = 1;
+
+ /**
+ * Set flow control register.
+ */
+ private static final int SIO_SET_FLOW_CTRL_REQUEST = 2;
+
+ /**
+ * Set baud rate.
+ */
+ private static final int SIO_SET_BAUD_RATE_REQUEST = 3;
+
+ /**
+ * Set the data characteristics of the port.
+ */
+ private static final int SIO_SET_DATA_REQUEST = 4;
+
+ private static final int SIO_RESET_SIO = 0;
+ private static final int SIO_RESET_PURGE_RX = 1;
+ private static final int SIO_RESET_PURGE_TX = 2;
+
+ public static final int FTDI_DEVICE_OUT_REQTYPE =
+ UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT;
+
+ public static final int FTDI_DEVICE_IN_REQTYPE =
+ UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN;
+
+ /**
+ * Length of the modem status header, transmitted with every read.
+ */
+ private static final int MODEM_STATUS_HEADER_LENGTH = 2;
+
+ private final String TAG = FtdiSerialDriver.class.getSimpleName();
+
+ private DeviceType mType;
+
+ private int mInterface = 0; /* INTERFACE_ANY */
+
+ private int mMaxPacketSize = 64; // TODO(mikey): detect
+
+ /**
+ * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads
+ * since it gives no indication of number of bytes read. Set this to
+ * {@code true} on platforms where it is fixed.
+ */
+ private static final boolean ENABLE_ASYNC_READS = false;
+
+ public FtdiSerialPort(UsbDevice device) {
+ super(device);
+ }
+
+ @Override
+ public UsbSerialDriver getDriver() {
+ return FtdiSerialDriver.this;
+ }
+
+ /**
+ * Filter FTDI status bytes from buffer
+ * @param src The source buffer (which contains status bytes)
+ * @param dest The destination buffer to write the status bytes into (can be src)
+ * @param totalBytesRead Number of bytes read to src
+ * @param maxPacketSize The USB endpoint max packet size
+ * @return The number of payload bytes
+ */
+ private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) {
+ final int packetsCount = totalBytesRead / maxPacketSize + 1;
+ for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) {
+ final int count = (packetIdx == (packetsCount - 1))
+ ? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH
+ : maxPacketSize - MODEM_STATUS_HEADER_LENGTH;
+ if (count > 0) {
+ System.arraycopy(src,
+ packetIdx * maxPacketSize + MODEM_STATUS_HEADER_LENGTH,
+ dest,
+ packetIdx * (maxPacketSize - MODEM_STATUS_HEADER_LENGTH),
+ count);
}
}
- reset();
- opened = true;
- } finally {
- if (!opened) {
- close();
+
+ return totalBytesRead - (packetsCount * 2);
+ }
+
+ public void reset() throws IOException {
+ int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
+ SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != 0) {
+ throw new IOException("Reset failed: result=" + result);
+ }
+
+ // TODO(mikey): autodetect.
+ mType = DeviceType.TYPE_R;
+ }
+
+ @Override
+ public void open(UsbDeviceConnection connection) throws IOException {
+ if (mConnection != null) {
+ throw new IOException("Already open");
+ }
+ boolean opened = false;
+ try {
+ for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
+ if (mConnection.claimInterface(mDevice.getInterface(i), true)) {
+ Log.d(TAG, "claimInterface " + i + " SUCCESS");
+ } else {
+ throw new IOException("Error claiming interface " + i);
+ }
+ }
+ reset();
+ opened = true;
+ } finally {
+ if (!opened) {
+ close();
+ } else {
+ mConnection = connection;
+ }
}
}
- }
- @Override
- public void close() {
- mConnection.close();
- }
-
- @Override
- public int read(byte[] dest, int timeoutMillis) throws IOException {
- final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0);
-
- if (ENABLE_ASYNC_READS) {
- final int readAmt;
- synchronized (mReadBufferLock) {
- // mReadBuffer is only used for maximum read size.
- readAmt = Math.min(dest.length, mReadBuffer.length);
+ @Override
+ public void close() throws IOException {
+ if (mConnection == null) {
+ throw new IOException("Already closed");
}
-
- final UsbRequest request = new UsbRequest();
- request.initialize(mConnection, endpoint);
-
- final ByteBuffer buf = ByteBuffer.wrap(dest);
- if (!request.queue(buf, readAmt)) {
- throw new IOException("Error queueing request.");
+ try {
+ mConnection.close();
+ } finally {
+ mConnection = null;
}
+ }
- final UsbRequest response = mConnection.requestWait();
- if (response == null) {
- throw new IOException("Null response");
- }
+ @Override
+ public int read(byte[] dest, int timeoutMillis) throws IOException {
+ final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0);
- final int payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH;
- if (payloadBytesRead > 0) {
- Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
- return payloadBytesRead;
+ if (ENABLE_ASYNC_READS) {
+ final int readAmt;
+ synchronized (mReadBufferLock) {
+ // mReadBuffer is only used for maximum read size.
+ readAmt = Math.min(dest.length, mReadBuffer.length);
+ }
+
+ final UsbRequest request = new UsbRequest();
+ request.initialize(mConnection, endpoint);
+
+ final ByteBuffer buf = ByteBuffer.wrap(dest);
+ if (!request.queue(buf, readAmt)) {
+ throw new IOException("Error queueing request.");
+ }
+
+ final UsbRequest response = mConnection.requestWait();
+ if (response == null) {
+ throw new IOException("Null response");
+ }
+
+ final int payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH;
+ if (payloadBytesRead > 0) {
+ Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
+ return payloadBytesRead;
+ } else {
+ return 0;
+ }
} else {
- return 0;
- }
- } else {
- final int totalBytesRead;
+ final int totalBytesRead;
- synchronized (mReadBufferLock) {
- final int readAmt = Math.min(dest.length, mReadBuffer.length);
- totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer,
- readAmt, timeoutMillis);
+ synchronized (mReadBufferLock) {
+ final int readAmt = Math.min(dest.length, mReadBuffer.length);
+ totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer,
+ readAmt, timeoutMillis);
- if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
- throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
+ if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
+ throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
+ }
+
+ return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize());
}
-
- return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize());
}
}
- }
- @Override
- public int write(byte[] src, int timeoutMillis) throws IOException {
- final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1);
- int offset = 0;
+ @Override
+ public int write(byte[] src, int timeoutMillis) throws IOException {
+ final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1);
+ int offset = 0;
- while (offset < src.length) {
- final int writeLength;
- final int amtWritten;
+ while (offset < src.length) {
+ final int writeLength;
+ final int amtWritten;
- synchronized (mWriteBufferLock) {
- final byte[] writeBuffer;
+ 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;
+ 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(endpoint, writeBuffer, writeLength,
+ timeoutMillis);
}
- amtWritten = mConnection.bulkTransfer(endpoint, writeBuffer, writeLength,
- timeoutMillis);
+ if (amtWritten <= 0) {
+ throw new IOException("Error writing " + writeLength
+ + " bytes at offset " + offset + " length=" + src.length);
+ }
+
+ Log.d(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength);
+ offset += amtWritten;
+ }
+ return offset;
+ }
+
+ private int setBaudRate(int baudRate) throws IOException {
+ long[] vals = convertBaudrate(baudRate);
+ long actualBaudrate = vals[0];
+ long index = vals[1];
+ long value = vals[2];
+ int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
+ SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index,
+ null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != 0) {
+ throw new IOException("Setting baudrate failed: result=" + result);
+ }
+ return (int) actualBaudrate;
+ }
+
+ @Override
+ public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
+ throws IOException {
+ setBaudRate(baudRate);
+
+ int config = dataBits;
+
+ switch (parity) {
+ case PARITY_NONE:
+ config |= (0x00 << 8);
+ break;
+ case PARITY_ODD:
+ config |= (0x01 << 8);
+ break;
+ case PARITY_EVEN:
+ config |= (0x02 << 8);
+ break;
+ case PARITY_MARK:
+ config |= (0x03 << 8);
+ break;
+ case PARITY_SPACE:
+ config |= (0x04 << 8);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown parity value: " + parity);
}
- if (amtWritten <= 0) {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length=" + src.length);
+ switch (stopBits) {
+ case STOPBITS_1:
+ config |= (0x00 << 11);
+ break;
+ case STOPBITS_1_5:
+ config |= (0x01 << 11);
+ break;
+ case STOPBITS_2:
+ config |= (0x02 << 11);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
}
- Log.d(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength);
- offset += amtWritten;
- }
- return offset;
- }
-
- private int setBaudRate(int baudRate) throws IOException {
- long[] vals = convertBaudrate(baudRate);
- long actualBaudrate = vals[0];
- long index = vals[1];
- long value = vals[2];
- int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
- SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index,
- null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0) {
- throw new IOException("Setting baudrate failed: result=" + result);
- }
- return (int) actualBaudrate;
- }
-
- @Override
- public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
- throws IOException {
- setBaudRate(baudRate);
-
- int config = dataBits;
-
- switch (parity) {
- case PARITY_NONE:
- config |= (0x00 << 8);
- break;
- case PARITY_ODD:
- config |= (0x01 << 8);
- break;
- case PARITY_EVEN:
- config |= (0x02 << 8);
- break;
- case PARITY_MARK:
- config |= (0x03 << 8);
- break;
- case PARITY_SPACE:
- config |= (0x04 << 8);
- break;
- default:
- throw new IllegalArgumentException("Unknown parity value: " + parity);
+ int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
+ SIO_SET_DATA_REQUEST, config, 0 /* index */,
+ null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != 0) {
+ throw new IOException("Setting parameters failed: result=" + result);
+ }
}
- switch (stopBits) {
- case STOPBITS_1:
- config |= (0x00 << 11);
- break;
- case STOPBITS_1_5:
- config |= (0x01 << 11);
- break;
- case STOPBITS_2:
- config |= (0x02 << 11);
- break;
- default:
- throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
- }
+ private long[] convertBaudrate(int baudrate) {
+ // TODO(mikey): Braindead transcription of libfti method. Clean up,
+ // using more idiomatic Java where possible.
+ int divisor = 24000000 / baudrate;
+ int bestDivisor = 0;
+ int bestBaud = 0;
+ int bestBaudDiff = 0;
+ int fracCode[] = {
+ 0, 3, 2, 4, 1, 5, 6, 7
+ };
- int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
- SIO_SET_DATA_REQUEST, config, 0 /* index */,
- null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0) {
- throw new IOException("Setting parameters failed: result=" + result);
- }
- }
+ for (int i = 0; i < 2; i++) {
+ int tryDivisor = divisor + i;
+ int baudEstimate;
+ int baudDiff;
- private long[] convertBaudrate(int baudrate) {
- // TODO(mikey): Braindead transcription of libfti method. Clean up,
- // using more idiomatic Java where possible.
- int divisor = 24000000 / baudrate;
- int bestDivisor = 0;
- int bestBaud = 0;
- int bestBaudDiff = 0;
- int fracCode[] = {
- 0, 3, 2, 4, 1, 5, 6, 7
- };
-
- for (int i = 0; i < 2; i++) {
- int tryDivisor = divisor + i;
- int baudEstimate;
- int baudDiff;
-
- if (tryDivisor <= 8) {
- // Round up to minimum supported divisor
- tryDivisor = 8;
- } else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) {
- // BM doesn't support divisors 9 through 11 inclusive
- tryDivisor = 12;
- } else if (divisor < 16) {
- // AM doesn't support divisors 9 through 15 inclusive
- tryDivisor = 16;
- } else {
- if (mType == DeviceType.TYPE_AM) {
- // TODO
+ if (tryDivisor <= 8) {
+ // Round up to minimum supported divisor
+ tryDivisor = 8;
+ } else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) {
+ // BM doesn't support divisors 9 through 11 inclusive
+ tryDivisor = 12;
+ } else if (divisor < 16) {
+ // AM doesn't support divisors 9 through 15 inclusive
+ tryDivisor = 16;
} else {
- if (tryDivisor > 0x1FFFF) {
- // Round down to maximum supported divisor value (for
- // BM)
- tryDivisor = 0x1FFFF;
+ if (mType == DeviceType.TYPE_AM) {
+ // TODO
+ } else {
+ if (tryDivisor > 0x1FFFF) {
+ // Round down to maximum supported divisor value (for
+ // BM)
+ tryDivisor = 0x1FFFF;
+ }
+ }
+ }
+
+ // Get estimated baud rate (to nearest integer)
+ baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor;
+
+ // Get absolute difference from requested baud rate
+ if (baudEstimate < baudrate) {
+ baudDiff = baudrate - baudEstimate;
+ } else {
+ baudDiff = baudEstimate - baudrate;
+ }
+
+ if (i == 0 || baudDiff < bestBaudDiff) {
+ // Closest to requested baud rate so far
+ bestDivisor = tryDivisor;
+ bestBaud = baudEstimate;
+ bestBaudDiff = baudDiff;
+ if (baudDiff == 0) {
+ // Spot on! No point trying
+ break;
}
}
}
- // Get estimated baud rate (to nearest integer)
- baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor;
-
- // Get absolute difference from requested baud rate
- if (baudEstimate < baudrate) {
- baudDiff = baudrate - baudEstimate;
- } else {
- baudDiff = baudEstimate - baudrate;
+ // Encode the best divisor value
+ long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14);
+ // Deal with special cases for encoded value
+ if (encodedDivisor == 1) {
+ encodedDivisor = 0; // 3000000 baud
+ } else if (encodedDivisor == 0x4001) {
+ encodedDivisor = 1; // 2000000 baud (BM only)
}
- if (i == 0 || baudDiff < bestBaudDiff) {
- // Closest to requested baud rate so far
- bestDivisor = tryDivisor;
- bestBaud = baudEstimate;
- bestBaudDiff = baudDiff;
- if (baudDiff == 0) {
- // Spot on! No point trying
- break;
+ // Split into "value" and "index" values
+ long value = encodedDivisor & 0xFFFF;
+ long index;
+ if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H
+ || mType == DeviceType.TYPE_4232H) {
+ index = (encodedDivisor >> 8) & 0xffff;
+ index &= 0xFF00;
+ index |= 0 /* TODO mIndex */;
+ } else {
+ index = (encodedDivisor >> 16) & 0xffff;
+ }
+
+ // Return the nearest baud rate
+ return new long[] {
+ bestBaud, index, value
+ };
+ }
+
+ @Override
+ public boolean getCD() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getCTS() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getDSR() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getDTR() throws IOException {
+ return false;
+ }
+
+ @Override
+ public void setDTR(boolean value) throws IOException {
+ }
+
+ @Override
+ public boolean getRI() throws IOException {
+ return false;
+ }
+
+ @Override
+ public boolean getRTS() throws IOException {
+ return false;
+ }
+
+ @Override
+ public void setRTS(boolean value) throws IOException {
+ }
+
+ @Override
+ public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
+ if (purgeReadBuffers) {
+ int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
+ SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != 0) {
+ throw new IOException("Flushing RX failed: result=" + result);
}
}
- }
- // Encode the best divisor value
- long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14);
- // Deal with special cases for encoded value
- if (encodedDivisor == 1) {
- encodedDivisor = 0; // 3000000 baud
- } else if (encodedDivisor == 0x4001) {
- encodedDivisor = 1; // 2000000 baud (BM only)
- }
-
- // Split into "value" and "index" values
- long value = encodedDivisor & 0xFFFF;
- long index;
- if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H
- || mType == DeviceType.TYPE_4232H) {
- index = (encodedDivisor >> 8) & 0xffff;
- index &= 0xFF00;
- index |= 0 /* TODO mIndex */;
- } else {
- index = (encodedDivisor >> 16) & 0xffff;
- }
-
- // Return the nearest baud rate
- return new long[] {
- bestBaud, index, value
- };
- }
-
- @Override
- public boolean getCD() throws IOException {
- return false;
- }
-
- @Override
- public boolean getCTS() throws IOException {
- return false;
- }
-
- @Override
- public boolean getDSR() throws IOException {
- return false;
- }
-
- @Override
- public boolean getDTR() throws IOException {
- return false;
- }
-
- @Override
- public void setDTR(boolean value) throws IOException {
- }
-
- @Override
- public boolean getRI() throws IOException {
- return false;
- }
-
- @Override
- public boolean getRTS() throws IOException {
- return false;
- }
-
- @Override
- public void setRTS(boolean value) throws IOException {
- }
-
- @Override
- public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
- if (purgeReadBuffers) {
- int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0) {
- throw new IOException("Flushing RX failed: result=" + result);
+ if (purgeWriteBuffers) {
+ int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
+ SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != 0) {
+ throw new IOException("Flushing RX failed: result=" + result);
+ }
}
+ return true;
}
-
- if (purgeWriteBuffers) {
- int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
- SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0) {
- throw new IOException("Flushing RX failed: result=" + result);
- }
- }
-
- return true;
}
public static Map getSupportedDevices() {
@@ -540,7 +572,7 @@ public class FtdiSerialDriver extends CommonUsbSerialDriver {
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI),
new int[] {
UsbId.FTDI_FT232R,
- UsbId.FTDI_FT231X,
+ UsbId.FTDI_FT231X,
});
return supportedDevices;
}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProbeTable.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProbeTable.java
new file mode 100644
index 0000000..db08019
--- /dev/null
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProbeTable.java
@@ -0,0 +1,108 @@
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
+ */
+
+package com.hoho.android.usbserial.driver;
+
+import android.util.Pair;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Maps (vendor id, product id) pairs to the corresponding serial driver.
+ *
+ * @author mike wakerly (opensource@hoho.com)
+ */
+public class ProbeTable {
+
+ private final Map, Class extends UsbSerialDriver>> mProbeTable =
+ new LinkedHashMap, Class extends UsbSerialDriver>>();
+
+ /**
+ * Adds or updates a (vendor, product) pair in the table.
+ *
+ * @param vendorId the USB vendor id
+ * @param productId the USB product id
+ * @param driverClass the driver class responsible for this pair
+ * @return {@code this}, for chaining
+ */
+ public ProbeTable addProduct(int vendorId, int productId,
+ Class extends UsbSerialDriver> driverClass) {
+ mProbeTable.put(Pair.create(vendorId, productId), driverClass);
+ return this;
+ }
+
+ /**
+ * Internal method to add all supported products from
+ * {@code getSupportedProducts} static method.
+ *
+ * @param driverClass
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ ProbeTable addDriver(Class extends UsbSerialDriver> driverClass) {
+ final Method method;
+
+ try {
+ method = driverClass.getMethod("getSupportedDevices");
+ } catch (SecurityException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+
+ final Map devices;
+ try {
+ devices = (Map) method.invoke(null);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+
+ for (Map.Entry entry : devices.entrySet()) {
+ final int vendorId = entry.getKey().intValue();
+ for (int productId : entry.getValue()) {
+ addProduct(vendorId, productId, driverClass);
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Returns the driver for the given (vendor, product) pair, or {@code null}
+ * if no match.
+ *
+ * @param vendorId the USB vendor id
+ * @param productId the USB product id
+ * @return the driver class matching this pair, or {@code null}
+ */
+ public Class extends UsbSerialDriver> findDriver(int vendorId, int productId) {
+ final Pair pair = Pair.create(vendorId, productId);
+ return mProbeTable.get(pair);
+ }
+
+}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
index 611498a..526f684 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/ProlificSerialDriver.java
@@ -13,7 +13,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
/*
@@ -36,481 +36,515 @@ import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
-public class ProlificSerialDriver extends CommonUsbSerialDriver {
- private static final int USB_READ_TIMEOUT_MILLIS = 1000;
- private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
-
- private static final int USB_RECIP_INTERFACE = 0x01;
-
- private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
- private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
-
- private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
- | UsbConstants.USB_TYPE_VENDOR;
-
- private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN
- | UsbConstants.USB_TYPE_VENDOR;
-
- private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
- | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-
- private static final int WRITE_ENDPOINT = 0x02;
- private static final int READ_ENDPOINT = 0x83;
- private static final int INTERRUPT_ENDPOINT = 0x81;
-
- private static final int FLUSH_RX_REQUEST = 0x08;
- private static final int FLUSH_TX_REQUEST = 0x09;
-
- private static final int SET_LINE_REQUEST = 0x20;
- private static final int SET_CONTROL_REQUEST = 0x22;
-
- private static final int CONTROL_DTR = 0x01;
- private static final int CONTROL_RTS = 0x02;
-
- private static final int STATUS_FLAG_CD = 0x01;
- private static final int STATUS_FLAG_DSR = 0x02;
- private static final int STATUS_FLAG_RI = 0x08;
- private static final int STATUS_FLAG_CTS = 0x80;
-
- private static final int STATUS_BUFFER_SIZE = 10;
- private static final int STATUS_BYTE_IDX = 8;
-
- private static final int DEVICE_TYPE_HX = 0;
- private static final int DEVICE_TYPE_0 = 1;
- private static final int DEVICE_TYPE_1 = 2;
-
- private int mDeviceType = DEVICE_TYPE_HX;
-
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
- private UsbEndpoint mInterruptEndpoint;
-
- private int mControlLinesValue = 0;
-
- private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1;
-
- private int mStatus = 0;
- private volatile Thread mReadStatusThread = null;
- private final Object mReadStatusThreadLock = new Object();
- boolean mStopReadStatusThread = false;
- private IOException mReadStatusException = null;
+public class ProlificSerialDriver implements UsbSerialDriver {
private final String TAG = ProlificSerialDriver.class.getSimpleName();
- private final byte[] inControlTransfer(int requestType, int request,
- int value, int index, int length) throws IOException {
- byte[] buffer = new byte[length];
- int result = mConnection.controlTransfer(requestType, request, value,
- index, buffer, length, USB_READ_TIMEOUT_MILLIS);
- if (result != length) {
- throw new IOException(
- String.format("ControlTransfer with value 0x%x failed: %d",
- value, result));
+ private final UsbDevice mDevice;
+ private final UsbSerialPort mPort;
+
+ public ProlificSerialDriver(UsbDevice device) {
+ mDevice = device;
+ mPort = new ProlificSerialPort(mDevice);
+ }
+
+ @Override
+ public List getPorts() {
+ return Collections.singletonList(mPort);
+ }
+
+ @Override
+ public UsbDevice getDevice() {
+ return mDevice;
+ }
+
+ class ProlificSerialPort extends CommonUsbSerialPort {
+
+ private static final int USB_READ_TIMEOUT_MILLIS = 1000;
+ private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
+
+ private static final int USB_RECIP_INTERFACE = 0x01;
+
+ private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
+ private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
+
+ private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
+ | UsbConstants.USB_TYPE_VENDOR;
+
+ private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN
+ | UsbConstants.USB_TYPE_VENDOR;
+
+ private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
+ | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+
+ private static final int WRITE_ENDPOINT = 0x02;
+ private static final int READ_ENDPOINT = 0x83;
+ private static final int INTERRUPT_ENDPOINT = 0x81;
+
+ private static final int FLUSH_RX_REQUEST = 0x08;
+ private static final int FLUSH_TX_REQUEST = 0x09;
+
+ private static final int SET_LINE_REQUEST = 0x20;
+ private static final int SET_CONTROL_REQUEST = 0x22;
+
+ private static final int CONTROL_DTR = 0x01;
+ private static final int CONTROL_RTS = 0x02;
+
+ private static final int STATUS_FLAG_CD = 0x01;
+ private static final int STATUS_FLAG_DSR = 0x02;
+ private static final int STATUS_FLAG_RI = 0x08;
+ private static final int STATUS_FLAG_CTS = 0x80;
+
+ private static final int STATUS_BUFFER_SIZE = 10;
+ private static final int STATUS_BYTE_IDX = 8;
+
+ private static final int DEVICE_TYPE_HX = 0;
+ private static final int DEVICE_TYPE_0 = 1;
+ private static final int DEVICE_TYPE_1 = 2;
+
+ private int mDeviceType = DEVICE_TYPE_HX;
+
+ private UsbEndpoint mReadEndpoint;
+ private UsbEndpoint mWriteEndpoint;
+ private UsbEndpoint mInterruptEndpoint;
+
+ private int mControlLinesValue = 0;
+
+ private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1;
+
+ private int mStatus = 0;
+ private volatile Thread mReadStatusThread = null;
+ private final Object mReadStatusThreadLock = new Object();
+ boolean mStopReadStatusThread = false;
+ private IOException mReadStatusException = null;
+
+
+ public ProlificSerialPort(UsbDevice device) {
+ super(device);
}
- return buffer;
- }
- private final void outControlTransfer(int requestType, int request,
- int value, int index, byte[] data) throws IOException {
- int length = (data == null) ? 0 : data.length;
- int result = mConnection.controlTransfer(requestType, request, value,
- index, data, length, USB_WRITE_TIMEOUT_MILLIS);
- if (result != length) {
- throw new IOException(
- String.format("ControlTransfer with value 0x%x failed: %d",
- value, result));
+ @Override
+ public UsbSerialDriver getDriver() {
+ return ProlificSerialDriver.this;
}
- }
- private final byte[] vendorIn(int value, int index, int length)
- throws IOException {
- return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
- PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
- }
-
- private final void vendorOut(int value, int index, byte[] data)
- throws IOException {
- outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
- PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
- }
-
- private final void ctrlOut(int request, int value, int index, byte[] data)
- throws IOException {
- outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
- data);
- }
-
- private void doBlackMagic() throws IOException {
- vendorIn(0x8484, 0, 1);
- vendorOut(0x0404, 0, null);
- vendorIn(0x8484, 0, 1);
- vendorIn(0x8383, 0, 1);
- vendorIn(0x8484, 0, 1);
- vendorOut(0x0404, 1, null);
- vendorIn(0x8484, 0, 1);
- vendorIn(0x8383, 0, 1);
- vendorOut(0, 1, null);
- vendorOut(1, 0, null);
- vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
- }
-
- private void resetDevice() throws IOException {
- purgeHwBuffers(true, true);
- }
-
- private void setControlLines(int newControlLinesValue) throws IOException {
- ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null);
- mControlLinesValue = newControlLinesValue;
- }
-
- private final void readStatusThreadFunction() {
- try {
- while (!mStopReadStatusThread) {
- byte[] buffer = new byte[STATUS_BUFFER_SIZE];
- int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint,
- buffer,
- STATUS_BUFFER_SIZE,
- 500);
- if (readBytesCount > 0) {
- if (readBytesCount == STATUS_BUFFER_SIZE) {
- mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
- } else {
- throw new IOException(
- String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d",
- STATUS_BUFFER_SIZE,
- readBytesCount));
- }
- }
+ private final byte[] inControlTransfer(int requestType, int request,
+ int value, int index, int length) throws IOException {
+ byte[] buffer = new byte[length];
+ int result = mConnection.controlTransfer(requestType, request, value,
+ index, buffer, length, USB_READ_TIMEOUT_MILLIS);
+ if (result != length) {
+ throw new IOException(
+ String.format("ControlTransfer with value 0x%x failed: %d",
+ value, result));
}
- } catch (IOException e) {
- mReadStatusException = e;
+ return buffer;
}
- }
- private final int getStatus() throws IOException {
- if ((mReadStatusThread == null) && (mReadStatusException == null)) {
- synchronized (mReadStatusThreadLock) {
- if (mReadStatusThread == null) {
+ private final void outControlTransfer(int requestType, int request,
+ int value, int index, byte[] data) throws IOException {
+ int length = (data == null) ? 0 : data.length;
+ int result = mConnection.controlTransfer(requestType, request, value,
+ index, data, length, USB_WRITE_TIMEOUT_MILLIS);
+ if (result != length) {
+ throw new IOException(
+ String.format("ControlTransfer with value 0x%x failed: %d",
+ value, result));
+ }
+ }
+
+ private final byte[] vendorIn(int value, int index, int length)
+ throws IOException {
+ return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
+ PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
+ }
+
+ private final void vendorOut(int value, int index, byte[] data)
+ throws IOException {
+ outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
+ PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
+ }
+
+ private void resetDevice() throws IOException {
+ purgeHwBuffers(true, true);
+ }
+
+ private final void ctrlOut(int request, int value, int index, byte[] data)
+ throws IOException {
+ outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
+ data);
+ }
+
+ private void doBlackMagic() throws IOException {
+ vendorIn(0x8484, 0, 1);
+ vendorOut(0x0404, 0, null);
+ vendorIn(0x8484, 0, 1);
+ vendorIn(0x8383, 0, 1);
+ vendorIn(0x8484, 0, 1);
+ vendorOut(0x0404, 1, null);
+ vendorIn(0x8484, 0, 1);
+ vendorIn(0x8383, 0, 1);
+ vendorOut(0, 1, null);
+ vendorOut(1, 0, null);
+ vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
+ }
+
+ private void setControlLines(int newControlLinesValue) throws IOException {
+ ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null);
+ mControlLinesValue = newControlLinesValue;
+ }
+
+ private final void readStatusThreadFunction() {
+ try {
+ while (!mStopReadStatusThread) {
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
- int readBytes = mConnection.bulkTransfer(mInterruptEndpoint,
+ int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint,
buffer,
STATUS_BUFFER_SIZE,
- 100);
- if (readBytes != STATUS_BUFFER_SIZE) {
- Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status");
- } else {
- mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
- }
-
- mReadStatusThread = new Thread(new Runnable() {
- @Override
- public void run() {
- readStatusThreadFunction();
+ 500);
+ if (readBytesCount > 0) {
+ if (readBytesCount == STATUS_BUFFER_SIZE) {
+ mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
+ } else {
+ throw new IOException(
+ String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d",
+ STATUS_BUFFER_SIZE,
+ readBytesCount));
}
- });
- mReadStatusThread.setDaemon(true);
- mReadStatusThread.start();
- }
- }
- }
-
- /* throw and clear an exception which occured in the status read thread */
- IOException readStatusException = mReadStatusException;
- if (mReadStatusException != null) {
- mReadStatusException = null;
- throw readStatusException;
- }
-
- return mStatus;
- }
-
- private final boolean testStatusFlag(int flag) throws IOException {
- return ((getStatus() & flag) == flag);
- }
-
- public ProlificSerialDriver(UsbDevice device, UsbDeviceConnection connection) {
- super(device, connection);
- }
-
- @Override
- public void open() throws IOException {
- UsbInterface usbInterface = mDevice.getInterface(0);
-
- if (!mConnection.claimInterface(usbInterface, true)) {
- throw new IOException("Error claiming Prolific interface 0");
- }
-
- boolean openSuccessful = false;
- try {
- for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
- UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i);
-
- switch (currentEndpoint.getAddress()) {
- case READ_ENDPOINT:
- mReadEndpoint = currentEndpoint;
- break;
-
- case WRITE_ENDPOINT:
- mWriteEndpoint = currentEndpoint;
- break;
-
- case INTERRUPT_ENDPOINT:
- mInterruptEndpoint = currentEndpoint;
- break;
- }
- }
-
- if (mDevice.getDeviceClass() == 0x02) {
- mDeviceType = DEVICE_TYPE_0;
- } else {
- try {
- Method getRawDescriptorsMethod
- = mConnection.getClass().getMethod("getRawDescriptors");
- byte[] rawDescriptors
- = (byte[]) getRawDescriptorsMethod.invoke(mConnection);
- byte maxPacketSize0 = rawDescriptors[7];
- if (maxPacketSize0 == 64) {
- mDeviceType = DEVICE_TYPE_HX;
- } else if ((mDevice.getDeviceClass() == 0x00)
- || (mDevice.getDeviceClass() == 0xff)) {
- mDeviceType = DEVICE_TYPE_1;
- } else {
- Log.w(TAG, "Could not detect PL2303 subtype, "
- + "Assuming that it is a HX device");
- mDeviceType = DEVICE_TYPE_HX;
}
- } catch (NoSuchMethodException e) {
- Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
- + "required for PL2303 subtype detection, not "
- + "available! Assuming that it is a HX device");
- mDeviceType = DEVICE_TYPE_HX;
- } catch (Exception e) {
- Log.e(TAG, "An unexpected exception occured while trying "
- + "to detect PL2303 subtype", e);
}
- }
-
- setControlLines(mControlLinesValue);
- resetDevice();
-
- doBlackMagic();
- openSuccessful = true;
- } finally {
- if (!openSuccessful) {
- try {
- mConnection.releaseInterface(usbInterface);
- } catch (Exception ingored) {
- // Do not cover possible exceptions
- }
+ } catch (IOException e) {
+ mReadStatusException = e;
}
}
- }
- @Override
- public void close() throws IOException {
- try {
- mStopReadStatusThread = true;
- synchronized (mReadStatusThreadLock) {
- if (mReadStatusThread != null) {
- try {
- mReadStatusThread.join();
- } catch (Exception e) {
- Log.w(TAG, "An error occured while waiting for status read thread", e);
+ private final int getStatus() throws IOException {
+ if ((mReadStatusThread == null) && (mReadStatusException == null)) {
+ synchronized (mReadStatusThreadLock) {
+ if (mReadStatusThread == null) {
+ byte[] buffer = new byte[STATUS_BUFFER_SIZE];
+ int readBytes = mConnection.bulkTransfer(mInterruptEndpoint,
+ buffer,
+ STATUS_BUFFER_SIZE,
+ 100);
+ if (readBytes != STATUS_BUFFER_SIZE) {
+ Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status");
+ } else {
+ mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
+ }
+
+ mReadStatusThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ readStatusThreadFunction();
+ }
+ });
+ mReadStatusThread.setDaemon(true);
+ mReadStatusThread.start();
}
}
}
- resetDevice();
- } finally {
- mConnection.releaseInterface(mDevice.getInterface(0));
- }
- }
-
- @Override
- public int read(byte[] dest, int timeoutMillis) throws IOException {
- synchronized (mReadBufferLock) {
- int readAmt = Math.min(dest.length, mReadBuffer.length);
- int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer,
- readAmt, timeoutMillis);
- if (numBytesRead < 0) {
- return 0;
+ /* throw and clear an exception which occured in the status read thread */
+ IOException readStatusException = mReadStatusException;
+ if (mReadStatusException != null) {
+ mReadStatusException = null;
+ throw readStatusException;
}
- System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
- return numBytesRead;
+
+ return mStatus;
}
- }
- @Override
- public int write(byte[] src, int timeoutMillis) throws IOException {
- int offset = 0;
+ private final boolean testStatusFlag(int flag) throws IOException {
+ return ((getStatus() & flag) == flag);
+ }
- while (offset < src.length) {
- final int writeLength;
- final int amtWritten;
+ @Override
+ public void open(UsbDeviceConnection connection) throws IOException {
+ if (mConnection != null) {
+ throw new IOException("Already open");
+ }
- synchronized (mWriteBufferLock) {
- final byte[] writeBuffer;
+ UsbInterface usbInterface = mDevice.getInterface(0);
- writeLength = Math.min(src.length - offset, mWriteBuffer.length);
- if (offset == 0) {
- writeBuffer = src;
+ if (!connection.claimInterface(usbInterface, true)) {
+ throw new IOException("Error claiming Prolific interface 0");
+ }
+
+ mConnection = connection;
+ boolean opened = false;
+ try {
+ for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
+ UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i);
+
+ switch (currentEndpoint.getAddress()) {
+ case READ_ENDPOINT:
+ mReadEndpoint = currentEndpoint;
+ break;
+
+ case WRITE_ENDPOINT:
+ mWriteEndpoint = currentEndpoint;
+ break;
+
+ case INTERRUPT_ENDPOINT:
+ mInterruptEndpoint = currentEndpoint;
+ break;
+ }
+ }
+
+ if (mDevice.getDeviceClass() == 0x02) {
+ mDeviceType = DEVICE_TYPE_0;
} else {
- // bulkTransfer does not support offsets, make a copy.
- System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
+ try {
+ Method getRawDescriptorsMethod
+ = mConnection.getClass().getMethod("getRawDescriptors");
+ byte[] rawDescriptors
+ = (byte[]) getRawDescriptorsMethod.invoke(mConnection);
+ byte maxPacketSize0 = rawDescriptors[7];
+ if (maxPacketSize0 == 64) {
+ mDeviceType = DEVICE_TYPE_HX;
+ } else if ((mDevice.getDeviceClass() == 0x00)
+ || (mDevice.getDeviceClass() == 0xff)) {
+ mDeviceType = DEVICE_TYPE_1;
+ } else {
+ Log.w(TAG, "Could not detect PL2303 subtype, "
+ + "Assuming that it is a HX device");
+ mDeviceType = DEVICE_TYPE_HX;
+ }
+ } catch (NoSuchMethodException e) {
+ Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
+ + "required for PL2303 subtype detection, not "
+ + "available! Assuming that it is a HX device");
+ mDeviceType = DEVICE_TYPE_HX;
+ } catch (Exception e) {
+ Log.e(TAG, "An unexpected exception occured while trying "
+ + "to detect PL2303 subtype", e);
+ }
}
- amtWritten = mConnection.bulkTransfer(mWriteEndpoint,
- writeBuffer, writeLength, timeoutMillis);
+ setControlLines(mControlLinesValue);
+ resetDevice();
+
+ doBlackMagic();
+ opened = true;
+ } finally {
+ if (!opened) {
+ mConnection = null;
+ connection.releaseInterface(usbInterface);
+ }
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (mConnection == null) {
+ throw new IOException("Already closed");
+ }
+ try {
+ mStopReadStatusThread = true;
+ synchronized (mReadStatusThreadLock) {
+ if (mReadStatusThread != null) {
+ try {
+ mReadStatusThread.join();
+ } catch (Exception e) {
+ Log.w(TAG, "An error occured while waiting for status read thread", e);
+ }
+ }
+ }
+ resetDevice();
+ } finally {
+ try {
+ mConnection.releaseInterface(mDevice.getInterface(0));
+ } finally {
+ mConnection = null;
+ }
+ }
+ }
+
+ @Override
+ public int read(byte[] dest, int timeoutMillis) throws IOException {
+ synchronized (mReadBufferLock) {
+ int readAmt = Math.min(dest.length, mReadBuffer.length);
+ int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer,
+ readAmt, timeoutMillis);
+ if (numBytesRead < 0) {
+ return 0;
+ }
+ System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
+ return numBytesRead;
+ }
+ }
+
+ @Override
+ public int write(byte[] src, int timeoutMillis) throws IOException {
+ 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);
+ }
+
+ offset += amtWritten;
+ }
+ return offset;
+ }
+
+ @Override
+ public void setParameters(int baudRate, int dataBits, int stopBits,
+ int parity) throws IOException {
+ if ((mBaudRate == baudRate) && (mDataBits == dataBits)
+ && (mStopBits == stopBits) && (mParity == parity)) {
+ // Make sure no action is performed if there is nothing to change
+ return;
}
- if (amtWritten <= 0) {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length="
- + src.length);
+ byte[] lineRequestData = new byte[7];
+
+ lineRequestData[0] = (byte) (baudRate & 0xff);
+ lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
+ lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
+ lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
+
+ switch (stopBits) {
+ case STOPBITS_1:
+ lineRequestData[4] = 0;
+ break;
+
+ case STOPBITS_1_5:
+ lineRequestData[4] = 1;
+ break;
+
+ case STOPBITS_2:
+ lineRequestData[4] = 2;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
}
- offset += amtWritten;
- }
- return offset;
- }
+ switch (parity) {
+ case PARITY_NONE:
+ lineRequestData[5] = 0;
+ break;
- @Override
- public void setParameters(int baudRate, int dataBits, int stopBits,
- int parity) throws IOException {
- if ((mBaudRate == baudRate) && (mDataBits == dataBits)
- && (mStopBits == stopBits) && (mParity == parity)) {
- // Make sure no action is performed if there is nothing to change
- return;
+ case PARITY_ODD:
+ lineRequestData[5] = 1;
+ break;
+
+ case PARITY_MARK:
+ lineRequestData[5] = 3;
+ break;
+
+ case PARITY_SPACE:
+ lineRequestData[5] = 4;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown parity value: " + parity);
+ }
+
+ lineRequestData[6] = (byte) dataBits;
+
+ ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
+
+ resetDevice();
+
+ mBaudRate = baudRate;
+ mDataBits = dataBits;
+ mStopBits = stopBits;
+ mParity = parity;
}
- byte[] lineRequestData = new byte[7];
-
- lineRequestData[0] = (byte) (baudRate & 0xff);
- lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
- lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
- lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
-
- switch (stopBits) {
- case STOPBITS_1:
- lineRequestData[4] = 0;
- break;
-
- case STOPBITS_1_5:
- lineRequestData[4] = 1;
- break;
-
- case STOPBITS_2:
- lineRequestData[4] = 2;
- break;
-
- default:
- throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
+ @Override
+ public boolean getCD() throws IOException {
+ return testStatusFlag(STATUS_FLAG_CD);
}
- switch (parity) {
- case PARITY_NONE:
- lineRequestData[5] = 0;
- break;
-
- case PARITY_ODD:
- lineRequestData[5] = 1;
- break;
-
- case PARITY_EVEN:
- lineRequestData[5] = 2;
- break;
-
- case PARITY_MARK:
- lineRequestData[5] = 3;
- break;
-
- case PARITY_SPACE:
- lineRequestData[5] = 4;
- break;
-
- default:
- throw new IllegalArgumentException("Unknown parity value: " + parity);
+ @Override
+ public boolean getCTS() throws IOException {
+ return testStatusFlag(STATUS_FLAG_CTS);
}
- lineRequestData[6] = (byte) dataBits;
-
- ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
-
- resetDevice();
-
- mBaudRate = baudRate;
- mDataBits = dataBits;
- mStopBits = stopBits;
- mParity = parity;
- }
-
- @Override
- public boolean getCD() throws IOException {
- return testStatusFlag(STATUS_FLAG_CD);
- }
-
- @Override
- public boolean getCTS() throws IOException {
- return testStatusFlag(STATUS_FLAG_CTS);
- }
-
- @Override
- public boolean getDSR() throws IOException {
- return testStatusFlag(STATUS_FLAG_DSR);
- }
-
- @Override
- public boolean getDTR() throws IOException {
- return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR);
- }
-
- @Override
- public void setDTR(boolean value) throws IOException {
- int newControlLinesValue;
- if (value) {
- newControlLinesValue = mControlLinesValue | CONTROL_DTR;
- } else {
- newControlLinesValue = mControlLinesValue & ~CONTROL_DTR;
- }
- setControlLines(newControlLinesValue);
- }
-
- @Override
- public boolean getRI() throws IOException {
- return testStatusFlag(STATUS_FLAG_RI);
- }
-
- @Override
- public boolean getRTS() throws IOException {
- return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS);
- }
-
- @Override
- public void setRTS(boolean value) throws IOException {
- int newControlLinesValue;
- if (value) {
- newControlLinesValue = mControlLinesValue | CONTROL_RTS;
- } else {
- newControlLinesValue = mControlLinesValue & ~CONTROL_RTS;
- }
- setControlLines(newControlLinesValue);
- }
-
- @Override
- public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
- if (purgeReadBuffers) {
- vendorOut(FLUSH_RX_REQUEST, 0, null);
+ @Override
+ public boolean getDSR() throws IOException {
+ return testStatusFlag(STATUS_FLAG_DSR);
}
- if (purgeWriteBuffers) {
- vendorOut(FLUSH_TX_REQUEST, 0, null);
+ @Override
+ public boolean getDTR() throws IOException {
+ return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR);
}
- return true;
+ @Override
+ public void setDTR(boolean value) throws IOException {
+ int newControlLinesValue;
+ if (value) {
+ newControlLinesValue = mControlLinesValue | CONTROL_DTR;
+ } else {
+ newControlLinesValue = mControlLinesValue & ~CONTROL_DTR;
+ }
+ setControlLines(newControlLinesValue);
+ }
+
+ @Override
+ public boolean getRI() throws IOException {
+ return testStatusFlag(STATUS_FLAG_RI);
+ }
+
+ @Override
+ public boolean getRTS() throws IOException {
+ return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS);
+ }
+
+ @Override
+ public void setRTS(boolean value) throws IOException {
+ int newControlLinesValue;
+ if (value) {
+ newControlLinesValue = mControlLinesValue | CONTROL_RTS;
+ } else {
+ newControlLinesValue = mControlLinesValue & ~CONTROL_RTS;
+ }
+ setControlLines(newControlLinesValue);
+ }
+
+ @Override
+ public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
+ if (purgeReadBuffers) {
+ vendorOut(FLUSH_RX_REQUEST, 0, null);
+ }
+
+ if (purgeWriteBuffers) {
+ vendorOut(FLUSH_TX_REQUEST, 0, null);
+ }
+
+ return purgeReadBuffers || purgeWriteBuffers;
+ }
}
public static Map getSupportedDevices() {
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java
index 2b228aa..b837c8a 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java
@@ -1,4 +1,5 @@
-/* Copyright 2012 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,8 +16,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
+
package com.hoho.android.usbserial.driver;
/**
@@ -52,7 +54,7 @@ public final class UsbId {
public static final int VENDOR_LEAFLABS = 0x1eaf;
public static final int LEAFLABS_MAPLE = 0x0004;
-
+
public static final int VENDOR_SILAB = 0x10c4;
public static final int SILAB_CP2102 = 0xea60;
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java
index d70712d..9130d97 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,196 +16,33 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.driver;
-import java.io.IOException;
+import android.hardware.usb.UsbDevice;
+
+import java.util.List;
/**
- * Driver interface for a USB serial device.
*
* @author mike wakerly (opensource@hoho.com)
*/
public interface UsbSerialDriver {
- /** 5 data bits. */
- public static final int DATABITS_5 = 5;
-
- /** 6 data bits. */
- public static final int DATABITS_6 = 6;
-
- /** 7 data bits. */
- public static final int DATABITS_7 = 7;
-
- /** 8 data bits. */
- public static final int DATABITS_8 = 8;
-
- /** No flow control. */
- public static final int FLOWCONTROL_NONE = 0;
-
- /** RTS/CTS input flow control. */
- public static final int FLOWCONTROL_RTSCTS_IN = 1;
-
- /** RTS/CTS output flow control. */
- public static final int FLOWCONTROL_RTSCTS_OUT = 2;
-
- /** XON/XOFF input flow control. */
- public static final int FLOWCONTROL_XONXOFF_IN = 4;
-
- /** XON/XOFF output flow control. */
- public static final int FLOWCONTROL_XONXOFF_OUT = 8;
-
- /** No parity. */
- public static final int PARITY_NONE = 0;
-
- /** Odd parity. */
- public static final int PARITY_ODD = 1;
-
- /** Even parity. */
- public static final int PARITY_EVEN = 2;
-
- /** Mark parity. */
- public static final int PARITY_MARK = 3;
-
- /** Space parity. */
- public static final int PARITY_SPACE = 4;
-
- /** 1 stop bit. */
- public static final int STOPBITS_1 = 1;
-
- /** 1.5 stop bits. */
- public static final int STOPBITS_1_5 = 3;
-
- /** 2 stop bits. */
- public static final int STOPBITS_2 = 2;
-
/**
- * Opens and initializes the device as a USB serial device. Upon success,
- * caller must ensure that {@link #close()} is eventually called.
+ * Returns the raw {@link UsbDevice} backing this port.
*
- * @throws IOException on error opening or initializing the device.
+ * @return the device
*/
- public void open() throws IOException;
+ public UsbDevice getDevice();
/**
- * Closes the serial device.
+ * Returns all available ports for this device. This list must have at least
+ * one entry.
*
- * @throws IOException on error closing the device.
+ * @return the ports
*/
- public void close() throws IOException;
-
- /**
- * Reads as many bytes as possible into the destination buffer.
- *
- * @param dest the destination byte buffer
- * @param timeoutMillis the timeout for reading
- * @return the actual number of bytes read
- * @throws IOException if an error occurred during reading
- */
- public int read(final byte[] dest, final int timeoutMillis) throws IOException;
-
- /**
- * Writes as many bytes as possible from the source buffer.
- *
- * @param src the source byte buffer
- * @param timeoutMillis the timeout for writing
- * @return the actual number of bytes written
- * @throws IOException if an error occurred during writing
- */
- public int write(final byte[] src, final int timeoutMillis) throws IOException;
-
- /**
- * Sets various serial port parameters.
- *
- * @param baudRate baud rate as an integer, for example {@code 115200}.
- * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6},
- * {@link #DATABITS_7}, or {@link #DATABITS_8}.
- * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or
- * {@link #STOPBITS_2}.
- * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD},
- * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or
- * {@link #PARITY_SPACE}.
- * @throws IOException on error setting the port parameters
- */
- public void setParameters(
- int baudRate, int dataBits, int stopBits, int parity) throws IOException;
-
- /**
- * Gets the CD (Carrier Detect) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getCD() throws IOException;
-
- /**
- * Gets the CTS (Clear To Send) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getCTS() throws IOException;
-
- /**
- * Gets the DSR (Data Set Ready) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getDSR() throws IOException;
-
- /**
- * Gets the DTR (Data Terminal Ready) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getDTR() throws IOException;
-
- /**
- * Sets the DTR (Data Terminal Ready) bit on the underlying UART, if
- * supported.
- *
- * @param value the value to set
- * @throws IOException if an error occurred during writing
- */
- public void setDTR(boolean value) throws IOException;
-
- /**
- * Gets the RI (Ring Indicator) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getRI() throws IOException;
-
- /**
- * Gets the RTS (Request To Send) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public boolean getRTS() throws IOException;
-
- /**
- * Sets the RTS (Request To Send) bit on the underlying UART, if
- * supported.
- *
- * @param value the value to set
- * @throws IOException if an error occurred during writing
- */
- public void setRTS(boolean value) throws IOException;
-
- /**
- * Flush non-transmitted output data and / or non-read input data
- * @param flushRX {@code true} to flush non-transmitted output data
- * @param flushTX {@code true} to flush non-read input data
- * @return {@code true} if the operation was successful, or
- * {@code false} if the operation is not supported by the driver or device
- * @throws IOException if an error occurred during flush
- */
- public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException;
-
+ public List getPorts();
}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialPort.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialPort.java
new file mode 100644
index 0000000..3cd0080
--- /dev/null
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialPort.java
@@ -0,0 +1,218 @@
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
+ */
+
+package com.hoho.android.usbserial.driver;
+
+import android.hardware.usb.UsbDeviceConnection;
+import android.hardware.usb.UsbManager;
+
+import java.io.IOException;
+
+/**
+ * Interface for a single serial port.
+ *
+ * @author mike wakerly (opensource@hoho.com)
+ */
+public interface UsbSerialPort {
+
+ /** 5 data bits. */
+ public static final int DATABITS_5 = 5;
+
+ /** 6 data bits. */
+ public static final int DATABITS_6 = 6;
+
+ /** 7 data bits. */
+ public static final int DATABITS_7 = 7;
+
+ /** 8 data bits. */
+ public static final int DATABITS_8 = 8;
+
+ /** No flow control. */
+ public static final int FLOWCONTROL_NONE = 0;
+
+ /** RTS/CTS input flow control. */
+ public static final int FLOWCONTROL_RTSCTS_IN = 1;
+
+ /** RTS/CTS output flow control. */
+ public static final int FLOWCONTROL_RTSCTS_OUT = 2;
+
+ /** XON/XOFF input flow control. */
+ public static final int FLOWCONTROL_XONXOFF_IN = 4;
+
+ /** XON/XOFF output flow control. */
+ public static final int FLOWCONTROL_XONXOFF_OUT = 8;
+
+ /** No parity. */
+ public static final int PARITY_NONE = 0;
+
+ /** Odd parity. */
+ public static final int PARITY_ODD = 1;
+
+ /** Even parity. */
+ public static final int PARITY_EVEN = 2;
+
+ /** Mark parity. */
+ public static final int PARITY_MARK = 3;
+
+ /** Space parity. */
+ public static final int PARITY_SPACE = 4;
+
+ /** 1 stop bit. */
+ public static final int STOPBITS_1 = 1;
+
+ /** 1.5 stop bits. */
+ public static final int STOPBITS_1_5 = 3;
+
+ /** 2 stop bits. */
+ public static final int STOPBITS_2 = 2;
+
+ public UsbSerialDriver getDriver();
+
+ /**
+ * Opens and initializes the port. Upon success, caller must ensure that
+ * {@link #close()} is eventually called.
+ *
+ * @param connection an open device connection, acquired with
+ * {@link UsbManager#openDevice(android.hardware.usb.UsbDevice)}
+ * @throws IOException on error opening or initializing the port.
+ */
+ public void open(UsbDeviceConnection connection) throws IOException;
+
+ /**
+ * Closes the port.
+ *
+ * @throws IOException on error closing the port.
+ */
+ public void close() throws IOException;
+
+ /**
+ * Reads as many bytes as possible into the destination buffer.
+ *
+ * @param dest the destination byte buffer
+ * @param timeoutMillis the timeout for reading
+ * @return the actual number of bytes read
+ * @throws IOException if an error occurred during reading
+ */
+ public int read(final byte[] dest, final int timeoutMillis) throws IOException;
+
+ /**
+ * Writes as many bytes as possible from the source buffer.
+ *
+ * @param src the source byte buffer
+ * @param timeoutMillis the timeout for writing
+ * @return the actual number of bytes written
+ * @throws IOException if an error occurred during writing
+ */
+ public int write(final byte[] src, final int timeoutMillis) throws IOException;
+
+ /**
+ * Sets various serial port parameters.
+ *
+ * @param baudRate baud rate as an integer, for example {@code 115200}.
+ * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6},
+ * {@link #DATABITS_7}, or {@link #DATABITS_8}.
+ * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or
+ * {@link #STOPBITS_2}.
+ * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD},
+ * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or
+ * {@link #PARITY_SPACE}.
+ * @throws IOException on error setting the port parameters
+ */
+ public void setParameters(
+ int baudRate, int dataBits, int stopBits, int parity) throws IOException;
+
+ /**
+ * Gets the CD (Carrier Detect) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getCD() throws IOException;
+
+ /**
+ * Gets the CTS (Clear To Send) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getCTS() throws IOException;
+
+ /**
+ * Gets the DSR (Data Set Ready) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getDSR() throws IOException;
+
+ /**
+ * Gets the DTR (Data Terminal Ready) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getDTR() throws IOException;
+
+ /**
+ * Sets the DTR (Data Terminal Ready) bit on the underlying UART, if
+ * supported.
+ *
+ * @param value the value to set
+ * @throws IOException if an error occurred during writing
+ */
+ public void setDTR(boolean value) throws IOException;
+
+ /**
+ * Gets the RI (Ring Indicator) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getRI() throws IOException;
+
+ /**
+ * Gets the RTS (Request To Send) bit from the underlying UART.
+ *
+ * @return the current state, or {@code false} if not supported.
+ * @throws IOException if an error occurred during reading
+ */
+ public boolean getRTS() throws IOException;
+
+ /**
+ * Sets the RTS (Request To Send) bit on the underlying UART, if
+ * supported.
+ *
+ * @param value the value to set
+ * @throws IOException if an error occurred during writing
+ */
+ public void setRTS(boolean value) throws IOException;
+
+ /**
+ * Flush non-transmitted output data and / or non-read input data
+ * @param flushRX {@code true} to flush non-transmitted output data
+ * @param flushTX {@code true} to flush non-read input data
+ * @return {@code true} if the operation was successful, or
+ * {@code false} if the operation is not supported by the driver or device
+ * @throws IOException if an error occurred during flush
+ */
+ public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException;
+
+}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java
index 420a8c2..d00bf63 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,233 +16,79 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.driver;
import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
/**
- * Helper class which finds compatible {@link UsbDevice}s and creates
- * {@link UsbSerialDriver} instances.
- *
- *
- * You don't need a Prober to use the rest of the library: it is perfectly
- * acceptable to instantiate driver instances manually. The Prober simply
- * provides convenience functions.
- *
- *
- * For most drivers, the corresponding {@link #probe(UsbManager, UsbDevice)}
- * method will either return an empty list (device unknown / unsupported) or a
- * singleton list. However, multi-port drivers may return multiple instances.
*
* @author mike wakerly (opensource@hoho.com)
*/
-public enum UsbSerialProber {
+public class UsbSerialProber {
- // TODO(mikey): Too much boilerplate.
+ private final ProbeTable mProbeTable;
+
+ public UsbSerialProber(ProbeTable probeTable) {
+ mProbeTable = probeTable;
+ }
+
+ public static UsbSerialProber getDefaultProber() {
+ final ProbeTable probeTable = new ProbeTable();
+ probeTable.addDriver(CdcAcmSerialDriver.class);
+ probeTable.addDriver(Cp2102SerialDriver.class);
+ probeTable.addDriver(FtdiSerialDriver.class);
+ probeTable.addDriver(ProlificSerialDriver.class);
+ return new UsbSerialProber(probeTable);
+ }
/**
- * Prober for {@link FtdiSerialDriver}.
+ * Finds and builds all possible {@link UsbSerialDriver UsbSerialDrivers}
+ * from the currently-attached {@link UsbDevice} hierarchy. This method does
+ * not require permission from the Android USB system, since it does not
+ * open any of the devices.
*
- * @see FtdiSerialDriver
+ * @param usbManager
+ * @return a list, possibly empty, of all compatible drivers
*/
- FTDI_SERIAL {
- @Override
- public List probe(final UsbManager manager, final UsbDevice usbDevice) {
- if (!testIfSupported(usbDevice, FtdiSerialDriver.getSupportedDevices())) {
- return Collections.emptyList();
- }
- final UsbDeviceConnection connection = manager.openDevice(usbDevice);
- if (connection == null) {
- return Collections.emptyList();
- }
- final UsbSerialDriver driver = new FtdiSerialDriver(usbDevice, connection);
- return Collections.singletonList(driver);
- }
- },
+ public List findAllDrivers(final UsbManager usbManager) {
+ final List result = new ArrayList();
- CDC_ACM_SERIAL {
- @Override
- public List probe(UsbManager manager, UsbDevice usbDevice) {
- if (!testIfSupported(usbDevice, CdcAcmSerialDriver.getSupportedDevices())) {
- return Collections.emptyList();
- }
- final UsbDeviceConnection connection = manager.openDevice(usbDevice);
- if (connection == null) {
- return Collections.emptyList();
- }
- final UsbSerialDriver driver = new CdcAcmSerialDriver(usbDevice, connection);
- return Collections.singletonList(driver);
- }
- },
-
- SILAB_SERIAL {
- @Override
- public List probe(final UsbManager manager, final UsbDevice usbDevice) {
- if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) {
- return Collections.emptyList();
- }
- final UsbDeviceConnection connection = manager.openDevice(usbDevice);
- if (connection == null) {
- return Collections.emptyList();
- }
- final UsbSerialDriver driver = new Cp2102SerialDriver(usbDevice, connection);
- return Collections.singletonList(driver);
- }
- },
-
- PROLIFIC_SERIAL {
- @Override
- public List probe(final UsbManager manager, final UsbDevice usbDevice) {
- if (!testIfSupported(usbDevice, ProlificSerialDriver.getSupportedDevices())) {
- return Collections.emptyList();
- }
- final UsbDeviceConnection connection = manager.openDevice(usbDevice);
- if (connection == null) {
- return Collections.emptyList();
- }
- final UsbSerialDriver driver = new ProlificSerialDriver(usbDevice, connection);
- return Collections.singletonList(driver);
- }
- };
-
- /**
- * Tests the supplied {@link UsbDevice} for compatibility with this enum
- * member, returning one or more driver instances if compatible.
- *
- * @param manager the {@link UsbManager} to use
- * @param usbDevice the raw {@link UsbDevice} to use
- * @return zero or more {@link UsbSerialDriver}, depending on compatibility
- * (never {@code null}).
- */
- protected abstract List probe(final UsbManager manager, final UsbDevice usbDevice);
-
- /**
- * Creates and returns a new {@link UsbSerialDriver} instance for the first
- * compatible {@link UsbDevice} found on the bus. If none are found,
- * returns {@code null}.
- *
- *
- * The order of devices is undefined, therefore if there are multiple
- * devices on the bus, the chosen device may not be predictable (clients
- * should use {@link #findAllDevices(UsbManager)} instead).
- *
- * @param usbManager the {@link UsbManager} to use.
- * @return the first available {@link UsbSerialDriver}, or {@code null} if
- * none are available.
- */
- public static UsbSerialDriver findFirstDevice(final UsbManager usbManager) {
for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) {
- for (final UsbSerialProber prober : values()) {
- final List probedDevices = prober.probe(usbManager, usbDevice);
- if (!probedDevices.isEmpty()) {
- return probedDevices.get(0);
+ final int vendorId = usbDevice.getVendorId();
+ final int productId = usbDevice.getProductId();
+
+ final Class extends UsbSerialDriver> driverClass =
+ mProbeTable.findDriver(vendorId, productId);
+ if (driverClass != null) {
+ final UsbSerialDriver driver;
+ try {
+ final Constructor extends UsbSerialDriver> ctor =
+ driverClass.getConstructor(UsbDevice.class);
+ driver = ctor.newInstance(usbDevice);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
}
+ result.add(driver);
}
}
- return null;
- }
-
- /**
- * Creates a new {@link UsbSerialDriver} instance for all compatible
- * {@link UsbDevice}s found on the bus. If no compatible devices are found,
- * the list will be empty.
- *
- * @param usbManager
- * @return
- */
- public static List findAllDevices(final UsbManager usbManager) {
- final List result = new ArrayList();
-
- // For each UsbDevice, call probe() for each prober.
- for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) {
- result.addAll(probeSingleDevice(usbManager, usbDevice));
- }
return result;
}
- /**
- * Special method for testing a specific device for driver support,
- * returning any compatible driver(s).
- *
- *
- * Clients should ordinarily use {@link #findAllDevices(UsbManager)}, which
- * operates against the entire bus of devices. This method is useful when
- * testing against only a single target is desired.
- *
- * @param usbManager the {@link UsbManager} to use.
- * @param usbDevice the device to test against.
- * @return a list containing zero or more {@link UsbSerialDriver} instances.
- */
- public static List probeSingleDevice(final UsbManager usbManager,
- UsbDevice usbDevice) {
- final List result = new ArrayList();
- for (final UsbSerialProber prober : values()) {
- final List probedDevices = prober.probe(usbManager, usbDevice);
- result.addAll(probedDevices);
- }
- return result;
- }
-
- /**
- * Deprecated; Use {@link #findFirstDevice(UsbManager)}.
- *
- * @param usbManager
- * @return
- */
- @Deprecated
- public static UsbSerialDriver acquire(final UsbManager usbManager) {
- return findFirstDevice(usbManager);
- }
-
- /**
- * Deprecated; use {@link #probeSingleDevice(UsbManager, UsbDevice)}.
- *
- * @param usbManager
- * @param usbDevice
- * @return
- */
- @Deprecated
- public static UsbSerialDriver acquire(final UsbManager usbManager, final UsbDevice usbDevice) {
- final List probedDevices = probeSingleDevice(usbManager, usbDevice);
- if (!probedDevices.isEmpty()) {
- return probedDevices.get(0);
- }
- return null;
- }
-
- /**
- * Returns {@code true} if the given device is found in the driver's
- * vendor/product map.
- *
- * @param usbDevice the device to test
- * @param supportedDevices map of vendor IDs to product ID(s)
- * @return {@code true} if supported
- */
- private static boolean testIfSupported(final UsbDevice usbDevice,
- final Map supportedDevices) {
- final int[] supportedProducts = supportedDevices.get(
- Integer.valueOf(usbDevice.getVendorId()));
- if (supportedProducts == null) {
- return false;
- }
-
- final int productId = usbDevice.getProductId();
- for (int supportedProductId : supportedProducts) {
- if (productId == supportedProductId) {
- return true;
- }
- }
- return false;
- }
-
}
diff --git a/UsbSerialLibrary/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java b/UsbSerialLibrary/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java
index d0be45e..d85a592 100644
--- a/UsbSerialLibrary/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java
+++ b/UsbSerialLibrary/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java
@@ -1,4 +1,5 @@
-/* Copyright 2011 Google Inc.
+/* Copyright 2011-2013 Google Inc.
+ * Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
- * Project home page: http://code.google.com/p/usb-serial-for-android/
+ * Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.util;
@@ -23,13 +24,13 @@ package com.hoho.android.usbserial.util;
import android.hardware.usb.UsbRequest;
import android.util.Log;
-import com.hoho.android.usbserial.driver.UsbSerialDriver;
+import com.hoho.android.usbserial.driver.UsbSerialPort;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
- * Utility class which services a {@link UsbSerialDriver} in its {@link #run()}
+ * Utility class which services a {@link UsbSerialPort} in its {@link #run()}
* method.
*
* @author mike wakerly (opensource@hoho.com)
@@ -42,7 +43,7 @@ public class SerialInputOutputManager implements Runnable {
private static final int READ_WAIT_MILLIS = 200;
private static final int BUFSIZ = 4096;
- private final UsbSerialDriver mDriver;
+ private final UsbSerialPort mDriver;
private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ);
@@ -77,14 +78,14 @@ public class SerialInputOutputManager implements Runnable {
/**
* Creates a new instance with no listener.
*/
- public SerialInputOutputManager(UsbSerialDriver driver) {
+ public SerialInputOutputManager(UsbSerialPort driver) {
this(driver, null);
}
/**
* Creates a new instance with the provided listener.
*/
- public SerialInputOutputManager(UsbSerialDriver driver, Listener listener) {
+ public SerialInputOutputManager(UsbSerialPort driver, Listener listener) {
mDriver = driver;
mListener = listener;
}