kopia lustrzana https://github.com/mik3y/usb-serial-for-android
rodzic
f801b31997
commit
b4b6d147ea
|
@ -2,4 +2,6 @@
|
|||
<resources>
|
||||
<!-- 0x0403 / 0x6001: FTDI FT232R UART -->
|
||||
<usb-device vendor-id="1027" product-id="24577" />
|
||||
<!-- 0x2341 / 0x0001: Arduino Uno -->
|
||||
<usb-device vendor-id="9025" product-id="1" />
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
package com.hoho.android.usbserial.driver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* USB CDC/ACM serial driver implementation.
|
||||
*
|
||||
* @author mike wakerly (opensource@hoho.com)
|
||||
*/
|
||||
public class CdcAcmSerialDriver implements UsbSerialDriver {
|
||||
private final String TAG = CdcAcmSerialDriver.class.getSimpleName();
|
||||
|
||||
private UsbDevice mDevice;
|
||||
private UsbDeviceConnection mConnection;
|
||||
private final byte[] mReadBuffer = new byte[4096];
|
||||
|
||||
private UsbInterface mControlInterface;
|
||||
private UsbInterface mDataInterface;
|
||||
|
||||
private UsbEndpoint mControlEndpoint;
|
||||
private UsbEndpoint mReadEndpoint;
|
||||
private UsbEndpoint mWriteEndpoint;
|
||||
|
||||
/**
|
||||
* @param usbDevice
|
||||
* @param connection
|
||||
*/
|
||||
public CdcAcmSerialDriver(UsbDevice usbDevice, UsbDeviceConnection connection) {
|
||||
mDevice = usbDevice;
|
||||
mConnection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() throws IOException {
|
||||
Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
|
||||
|
||||
Log.d(TAG, "Claiming control interface.");
|
||||
mControlInterface = mDevice.getInterface(0);
|
||||
Log.d(TAG, "Control iface=" + mControlInterface);
|
||||
// class should be USB_CLASS_COMM
|
||||
|
||||
if (!mConnection.claimInterface(mControlInterface, true)) {
|
||||
throw new IOException("Could not claim control interface.");
|
||||
}
|
||||
mControlEndpoint = mControlInterface.getEndpoint(0);
|
||||
Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection());
|
||||
|
||||
Log.d(TAG, "Claiming data interface.");
|
||||
mDataInterface = mDevice.getInterface(1);
|
||||
Log.d(TAG, "data iface=" + mDataInterface);
|
||||
// class should be USB_CLASS_CDC_DATA
|
||||
|
||||
if (!mConnection.claimInterface(mDataInterface, true)) {
|
||||
throw new IOException("Could not claim data interface.");
|
||||
}
|
||||
mReadEndpoint = mDataInterface.getEndpoint(1);
|
||||
Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection());
|
||||
mWriteEndpoint = mDataInterface.getEndpoint(0);
|
||||
Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection());
|
||||
|
||||
Log.d(TAG, "Setting line coding");
|
||||
setBaudRate(115200);
|
||||
|
||||
}
|
||||
|
||||
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 int sendAcmControlMessage(int request, int value, byte[] buf) {
|
||||
return mConnection.controlTransfer(USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000);
|
||||
}
|
||||
|
||||
private int setAcmLineCoding(int bitRate, int stopBits, int parity, int dataBits) {
|
||||
byte[] msg = {
|
||||
(byte) ( bitRate & 0xff),
|
||||
(byte) ((bitRate >> 8 ) & 0xff),
|
||||
(byte) ((bitRate >> 16) & 0xff),
|
||||
(byte) ((bitRate >> 24) & 0xff),
|
||||
|
||||
(byte) stopBits,
|
||||
(byte) parity,
|
||||
(byte) dataBits};
|
||||
return sendAcmControlMessage(SET_LINE_CODING, 0, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
mConnection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] dest, int timeoutMillis) throws IOException {
|
||||
int readAmt = Math.min(dest.length, mReadBuffer.length);
|
||||
readAmt = Math.min(readAmt, mReadEndpoint.getMaxPacketSize());
|
||||
final int transferred = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
|
||||
timeoutMillis);
|
||||
|
||||
if (transferred < 0) {
|
||||
throw new IOException("Timeout reading timeoutMillis=" + timeoutMillis);
|
||||
}
|
||||
System.arraycopy(mReadBuffer, 0, dest, 0, transferred);
|
||||
return transferred;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(byte[] src, int timeoutMillis) throws IOException {
|
||||
int offset = 0;
|
||||
final int chunksize = mWriteEndpoint.getMaxPacketSize();
|
||||
|
||||
while (offset < src.length) {
|
||||
final byte[] writeBuffer;
|
||||
final int writeLength;
|
||||
|
||||
// bulkTransfer does not support offsets; make a copy if necessary.
|
||||
writeLength = Math.min(src.length - offset, chunksize);
|
||||
if (offset == 0) {
|
||||
writeBuffer = src;
|
||||
} else {
|
||||
writeBuffer = Arrays.copyOfRange(src, offset, offset + writeLength);
|
||||
}
|
||||
|
||||
final int amt = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
|
||||
timeoutMillis);
|
||||
if (amt <= 0) {
|
||||
throw new IOException("Error writing " + writeLength
|
||||
+ " bytes at offset " + offset + " length=" + src.length);
|
||||
}
|
||||
Log.d(TAG, "Wrote amt=" + amt + " attempted=" + writeBuffer.length);
|
||||
offset += amt;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBaudRate(int baudRate) throws IOException {
|
||||
setAcmLineCoding(baudRate, 0, 0, 8);
|
||||
return baudRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsbDevice getDevice() {
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
public static boolean probe(UsbDevice usbDevice) {
|
||||
return usbDevice.getVendorId() == 0x2341 && usbDevice.getProductId() == 0x001;
|
||||
}
|
||||
|
||||
}
|
|
@ -49,6 +49,20 @@ public enum UsbSerialProber {
|
|||
}
|
||||
return new FtdiSerialDriver(usbDevice, connection);
|
||||
}
|
||||
},
|
||||
|
||||
CDC_ACM_SERIAL {
|
||||
@Override
|
||||
public UsbSerialDriver getDevice(UsbManager manager, UsbDevice usbDevice) {
|
||||
if (!CdcAcmSerialDriver.probe(usbDevice)) {
|
||||
return null;
|
||||
}
|
||||
final UsbDeviceConnection connection = manager.openDevice(usbDevice);
|
||||
if (connection == null) {
|
||||
return null;
|
||||
}
|
||||
return new CdcAcmSerialDriver(usbDevice, connection);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Ładowanie…
Reference in New Issue