UsbSerial/usbserial/src/main/java/com/felhr/usbserial/FTDISerialDevice.java

390 wiersze
11 KiB
Java

package com.felhr.usbserial;
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.hardware.usb.UsbRequest;
import android.util.Log;
public class FTDISerialDevice extends UsbSerialDevice
{
private static final String CLASS_ID = FTDISerialDevice.class.getSimpleName();
private static final int FTDI_SIO_RESET = 0;
private static final int FTDI_SIO_MODEM_CTRL = 1;
private static final int FTDI_SIO_SET_FLOW_CTRL = 2;
private static final int FTDI_SIO_SET_BAUD_RATE = 3;
private static final int FTDI_SIO_SET_DATA = 4;
private static final int FTDI_REQTYPE_HOST2DEVICE = 0x40;
public static final int FTDI_BAUDRATE_300 = 0x2710;
public static final int FTDI_BAUDRATE_600 = 0x1388;
public static final int FTDI_BAUDRATE_1200 = 0x09c4;
public static final int FTDI_BAUDRATE_2400 = 0x04e2;
public static final int FTDI_BAUDRATE_4800 = 0x0271;
public static final int FTDI_BAUDRATE_9600 = 0x4138;
public static final int FTDI_BAUDRATE_19200 = 0x809c;
public static final int FTDI_BAUDRATE_38400 = 0xc04e;
public static final int FTDI_BAUDRATE_57600 = 0x0034;
public static final int FTDI_BAUDRATE_115200 = 0x001a;
public static final int FTDI_BAUDRATE_230400 = 0x000d;
public static final int FTDI_BAUDRATE_460800 = 0x4006;
public static final int FTDI_BAUDRATE_921600 = 0x8003;
/***
* Default Serial Configuration
* Baud rate: 9600
* Data bits: 8
* Stop bits: 1
* Parity: None
* Flow Control: Off
*/
private static final int FTDI_SET_DATA_DEFAULT = 0x0008;
private static final int FTDI_SET_MODEM_CTRL_DEFAULT1 = 0x0101;
private static final int FTDI_SET_MODEM_CTRL_DEFAULT2 = 0x0202;
private static final int FTDI_SET_MODEM_CTRL_DEFAULT3 = 0x0100;
private static final int FTDI_SET_MODEM_CTRL_DEFAULT4 = 0x0200;
private static final int FTDI_SET_FLOW_CTRL_DEFAULT = 0x0000;
private int currentSioSetData = 0x0000;
private UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
public FTDISerialDevice(UsbDevice device, UsbDeviceConnection connection)
{
this(device, connection, -1);
}
public FTDISerialDevice(UsbDevice device, UsbDeviceConnection connection, int iface)
{
super(device, connection);
mInterface = device.getInterface(iface >= 0 ? iface : 0);
}
@Override
public boolean open()
{
if(connection.claimInterface(mInterface, true))
{
Log.i(CLASS_ID, "Interface succesfully claimed");
}else
{
Log.i(CLASS_ID, "Interface could not be claimed");
return false;
}
// Assign endpoints
int numberEndpoints = mInterface.getEndpointCount();
for(int i=0;i<=numberEndpoints-1;i++)
{
UsbEndpoint endpoint = mInterface.getEndpoint(i);
if(endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK
&& endpoint.getDirection() == UsbConstants.USB_DIR_IN)
{
inEndpoint = endpoint;
}else
{
outEndpoint = endpoint;
}
}
// Default Setup
if(setControlCommand(FTDI_SIO_RESET, 0x00, 0, null) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_DATA, FTDI_SET_DATA_DEFAULT, 0, null) < 0)
return false;
currentSioSetData = FTDI_SET_DATA_DEFAULT;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT1, 0, null) < 0)
return false;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT2, 0, null) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_BAUD_RATE, FTDI_BAUDRATE_9600, 0, null) < 0)
return false;
// Initialize UsbRequest
requestIN = new UsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
return true;
}
@Override
public void close()
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0, null);
currentSioSetData = 0x0000;
killWorkingThread();
killWriteThread();
connection.releaseInterface(mInterface);
}
@Override
public void setBaudRate(int baudRate)
{
int value = 0;
if(baudRate >= 0 && baudRate <= 300 )
value = FTDI_BAUDRATE_300;
else if(baudRate > 300 && baudRate <= 600)
value = FTDI_BAUDRATE_600;
else if(baudRate > 600 && baudRate <= 1200)
value = FTDI_BAUDRATE_1200;
else if(baudRate > 1200 && baudRate <= 2400)
value = FTDI_BAUDRATE_2400;
else if(baudRate > 2400 && baudRate <= 4800)
value = FTDI_BAUDRATE_4800;
else if(baudRate > 4800 && baudRate <= 9600)
value = FTDI_BAUDRATE_9600;
else if(baudRate > 9600 && baudRate <=19200)
value = FTDI_BAUDRATE_19200;
else if(baudRate > 19200 && baudRate <= 38400)
value = FTDI_BAUDRATE_38400;
else if(baudRate > 19200 && baudRate <= 57600)
value = FTDI_BAUDRATE_57600;
else if(baudRate > 57600 && baudRate <= 115200)
value = FTDI_BAUDRATE_115200;
else if(baudRate > 115200 && baudRate <= 230400)
value = FTDI_BAUDRATE_230400;
else if(baudRate > 230400 && baudRate <= 460800)
value = FTDI_BAUDRATE_460800;
else if(baudRate > 460800 && baudRate <= 921600)
value = FTDI_BAUDRATE_921600;
else if(baudRate > 921600)
value = FTDI_BAUDRATE_921600;
else
value = FTDI_BAUDRATE_9600;
setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0, null);
}
@Override
public void setDataBits(int dataBits)
{
switch(dataBits)
{
case UsbSerialInterface.DATA_BITS_5:
currentSioSetData |= 1;
currentSioSetData &= ~(1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.DATA_BITS_6:
currentSioSetData &= ~1;
currentSioSetData |= (1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.DATA_BITS_7:
currentSioSetData |= 1;
currentSioSetData |= (1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.DATA_BITS_8:
currentSioSetData &= ~1;
currentSioSetData &= ~(1 << 1);
currentSioSetData &= ~(1 << 2);
currentSioSetData |= (1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
default:
currentSioSetData &= ~1;
currentSioSetData &= ~(1 << 1);
currentSioSetData &= ~(1 << 2);
currentSioSetData |= (1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
}
}
@Override
public void setStopBits(int stopBits)
{
switch(stopBits)
{
case UsbSerialInterface.STOP_BITS_1:
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.STOP_BITS_15:
currentSioSetData |= (1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.STOP_BITS_2:
currentSioSetData &= ~(1 << 11);
currentSioSetData |= (1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
default:
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
}
}
@Override
public void setParity(int parity)
{
switch(parity)
{
case UsbSerialInterface.PARITY_NONE:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.PARITY_ODD:
currentSioSetData |= (1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.PARITY_EVEN:
currentSioSetData &= ~(1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.PARITY_MARK:
currentSioSetData |= (1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
case UsbSerialInterface.PARITY_SPACE:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData |= (1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
default:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
break;
}
}
@Override
public void setFlowControl(int flowControl)
{
switch(flowControl)
{
case UsbSerialInterface.FLOW_CONTROL_OFF:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
break;
case UsbSerialInterface.FLOW_CONTROL_RTS_CTS:
int indexRTSCTS = 0x0001;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexRTSCTS, null);
break;
case UsbSerialInterface.FLOW_CONTROL_DSR_DTR:
int indexDSRDTR = 0x0002;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexDSRDTR , null);
break;
case UsbSerialInterface.FLOW_CONTROL_XON_XOFF:
int indexXONXOFF = 0x0004;
int wValue = 0x1311;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, wValue, indexXONXOFF , null);
break;
default:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
break;
}
}
private int setControlCommand(int request, int value, int index, byte[] data)
{
int dataLength = 0;
if(data != null)
{
dataLength = data.length;
}
int response = connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, request, value, mInterface.getId() + 1 + index, data, dataLength, USB_TIMEOUT);
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
return response;
}
public static class FTDIUtilities
{
// Special treatment needed to FTDI devices
public static byte[] adaptArray(byte[] ftdiData)
{
int length = ftdiData.length;
if(length > 64)
{
int n = 1;
int p = 64;
// Precalculate length without FTDI headers
while(p < length)
{
n++;
p = n*64;
}
int realLength = length - n*2;
byte[] data = new byte[realLength];
copyData(ftdiData, data);
return data;
}else
{
return Arrays.copyOfRange(ftdiData, 2, length);
}
}
// Copy data without FTDI headers
private static void copyData(byte[] src, byte[] dst)
{
int i = 0; // src index
int j = 0; // dst index
while(i <= src.length-1)
{
if(i != 0 && i != 1)
{
if(i % 64 == 0 && i >= 64)
{
i += 2;
}else
{
dst[j] = src[i];
i++;
j++;
}
}else
{
i++;
}
}
}
}
}