mirror of
https://github.com/mik3y/usb-serial-for-android
synced 2025-06-10 01:16:27 +00:00
added support for cp2102 device
This commit is contained in:
parent
c3ac464ab3
commit
2b3528b425
@ -9,4 +9,7 @@
|
|||||||
<!-- 0x16C0 / 0x0483: Teensyduino -->
|
<!-- 0x16C0 / 0x0483: Teensyduino -->
|
||||||
<usb-device vendor-id="5824" product-id="1155" />
|
<usb-device vendor-id="5824" product-id="1155" />
|
||||||
|
|
||||||
|
<!-- 0x10C4 / 0xEA60: CP210x UART Bridge -->
|
||||||
|
<usb-device vender-id="4292" product-id="60000" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -0,0 +1,275 @@
|
|||||||
|
package com.hoho.android.usbserial.driver;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import android.hardware.usb.UsbConstants;
|
||||||
|
import android.hardware.usb.UsbDevice;
|
||||||
|
import android.hardware.usb.UsbDeviceConnection;
|
||||||
|
import android.hardware.usb.UsbEndpoint;
|
||||||
|
import android.hardware.usb.UsbInterface;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class Cp2102SerialDriver extends UsbSerialDriver {
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
} 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) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
while (offset < src.length) {
|
||||||
|
final int writeLength;
|
||||||
|
final int amtWritten;
|
||||||
|
|
||||||
|
synchronized (mWriteBufferLock) {
|
||||||
|
final byte[] writeBuffer;
|
||||||
|
|
||||||
|
writeLength = Math.min(src.length - offset, mWriteBuffer.length);
|
||||||
|
if (offset == 0) {
|
||||||
|
writeBuffer = src;
|
||||||
|
} else {
|
||||||
|
// bulkTransfer does not support offsets, make a copy.
|
||||||
|
System.arraycopy(src, offset, mWriteBuffer, 0, writeLength);
|
||||||
|
writeBuffer = mWriteBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
|
||||||
|
timeoutMillis);
|
||||||
|
}
|
||||||
|
if (amtWritten <= 0) {
|
||||||
|
throw new IOException("Error writing " + writeLength
|
||||||
|
+ " bytes at offset " + offset + " length=" + src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
|
||||||
|
offset += amtWritten;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public int setBaudRate(int baudRate) throws IOException {
|
||||||
|
byte[] data = new byte[] {
|
||||||
|
(byte) ( baudRate & 0xff),
|
||||||
|
(byte) ((baudRate >> 8 ) & 0xff),
|
||||||
|
(byte) ((baudRate >> 16) & 0xff),
|
||||||
|
(byte) ((baudRate >> 24) & 0xff)
|
||||||
|
};
|
||||||
|
mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
|
||||||
|
0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
|
||||||
|
return baudRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Integer, int[]> getSupportedDevices() {
|
||||||
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
||||||
|
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILAB),
|
||||||
|
new int[] {
|
||||||
|
UsbId.SILAB_CP2102
|
||||||
|
});
|
||||||
|
return supportedDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -52,6 +52,9 @@ public final class UsbId {
|
|||||||
public static final int VENDOR_LEAFLABS = 0x1eaf;
|
public static final int VENDOR_LEAFLABS = 0x1eaf;
|
||||||
public static final int LEAFLABS_MAPLE = 0x0004;
|
public static final int LEAFLABS_MAPLE = 0x0004;
|
||||||
|
|
||||||
|
public static final int VENDOR_SILAB = 0x10c4;
|
||||||
|
public static final int SILAB_CP2102 = 0xea60;
|
||||||
|
|
||||||
private UsbId() {
|
private UsbId() {
|
||||||
throw new IllegalAccessError("Non-instantiable class.");
|
throw new IllegalAccessError("Non-instantiable class.");
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,20 @@ public enum UsbSerialProber {
|
|||||||
}
|
}
|
||||||
return new CdcAcmSerialDriver(usbDevice, connection);
|
return new CdcAcmSerialDriver(usbDevice, connection);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
SILAB_SERIAL {
|
||||||
|
@Override
|
||||||
|
public UsbSerialDriver getDevice(final UsbManager manager, final UsbDevice usbDevice) {
|
||||||
|
if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
|
||||||
|
if (connection == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Cp2102SerialDriver(usbDevice, connection);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user