Merge pull request #212 from Arneball/reuseempty

Reuse same instance of byte array when the destination array is empty
pull/216/head
Felipe Herranz 2019-02-23 19:00:16 +01:00 zatwierdzone przez GitHub
commit 234c83dd28
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
3 zmienionych plików z 136 dodań i 93 usunięć

Wyświetl plik

@ -63,6 +63,7 @@ public class FTDISerialDevice extends UsbSerialDevice
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 static final byte[] EMPTY_BYTE_ARRAY = {};
private int currentSioSetData = 0x0000;
@ -140,8 +141,8 @@ public class FTDISerialDevice extends UsbSerialDevice
@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);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0);
currentSioSetData = 0x0000;
killWorkingThread();
killWriteThread();
@ -175,8 +176,8 @@ public class FTDISerialDevice extends UsbSerialDevice
@Override
public void syncClose()
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0);
currentSioSetData = 0x0000;
connection.releaseInterface(mInterface);
isOpen = false;
@ -216,7 +217,7 @@ public class FTDISerialDevice extends UsbSerialDevice
value = FTDI_BAUDRATE_921600;
else
value = FTDI_BAUDRATE_9600;
setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0, null);
setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0);
}
@Override
@ -229,35 +230,35 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
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);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
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);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
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);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~1;
currentSioSetData &= ~(1 << 1);
currentSioSetData &= ~(1 << 2);
currentSioSetData |= (1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
}
@ -272,25 +273,25 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.STOP_BITS_15:
currentSioSetData |= (1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.STOP_BITS_2:
currentSioSetData &= ~(1 << 11);
currentSioSetData |= (1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
}
}
@ -304,37 +305,37 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_ODD:
currentSioSetData |= (1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_EVEN:
currentSioSetData &= ~(1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_MARK:
currentSioSetData |= (1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_SPACE:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData |= (1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
}
@ -346,7 +347,7 @@ public class FTDISerialDevice extends UsbSerialDevice
switch(flowControl)
{
case UsbSerialInterface.FLOW_CONTROL_OFF:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0);
rtsCtsEnabled = false;
dtrDsrEnabled = false;
break;
@ -354,21 +355,21 @@ public class FTDISerialDevice extends UsbSerialDevice
rtsCtsEnabled = true;
dtrDsrEnabled = false;
int indexRTSCTS = 0x0001;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexRTSCTS, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexRTSCTS);
break;
case UsbSerialInterface.FLOW_CONTROL_DSR_DTR:
dtrDsrEnabled = true;
rtsCtsEnabled = false;
int indexDSRDTR = 0x0002;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexDSRDTR , null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexDSRDTR);
break;
case UsbSerialInterface.FLOW_CONTROL_XON_XOFF:
int indexXONXOFF = 0x0004;
int wValue = 0x1311;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, wValue, indexXONXOFF , null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, wValue, indexXONXOFF);
break;
default:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0);
break;
}
}
@ -378,10 +379,10 @@ public class FTDISerialDevice extends UsbSerialDevice
{
if(state)
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_HIGH, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_HIGH, 0);
}else
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_LOW, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_LOW, 0);
}
}
@ -390,10 +391,10 @@ public class FTDISerialDevice extends UsbSerialDevice
{
if(state)
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_HIGH, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_HIGH, 0);
}else
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_LOW, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_LOW, 0);
}
}
@ -461,18 +462,18 @@ public class FTDISerialDevice extends UsbSerialDevice
// Default Setup
firstTime = true;
if(setControlCommand(FTDI_SIO_RESET, 0x00, 0, null) < 0)
if(setControlCommand(FTDI_SIO_RESET, 0x00, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_DATA, FTDI_SET_DATA_DEFAULT, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_DATA, FTDI_SET_DATA_DEFAULT, 0) < 0)
return false;
currentSioSetData = FTDI_SET_DATA_DEFAULT;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT1, 0, null) < 0)
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT1, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT2, 0, null) < 0)
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT2, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_BAUD_RATE, FTDI_BAUDRATE_9600, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_BAUD_RATE, FTDI_BAUDRATE_9600, 0) < 0)
return false;
// Flow control disabled by default
@ -482,44 +483,62 @@ public class FTDISerialDevice extends UsbSerialDevice
return true;
}
private int setControlCommand(int request, int value, int index, byte[] data)
private int setControlCommand(int request, int value, int index)
{
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);
int response = connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, request, value, mInterface.getId() + 1 + index, null, dataLength, USB_TIMEOUT);
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
return response;
}
// Special treatment needed to FTDI devices
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 if (length == 2) // special case optimization that returns the same instance.
{
return EMPTY_BYTE_ARRAY;
}
else
{
return Arrays.copyOfRange(ftdiData, 2, length);
}
}
// Copy data without FTDI headers
private static void copyData(byte[] src, byte[] dst)
{
int srcPos = 2, dstPos = 0;
while(srcPos - 2 <= src.length - 64)
{
System.arraycopy(src, srcPos, dst, dstPos, 62);
srcPos += 64;
dstPos += 62;
}
int remaining = src.length - srcPos + 2;
if (remaining > 0)
{
System.arraycopy(src, srcPos, dst, dstPos, remaining - 2);
}
}
public class FTDIUtilities
{
// Special treatment needed to FTDI devices
public 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);
}
}
public void checkModemStatus(byte[] data)
{
if(data.length == 0) // Safeguard for zero length arrays
@ -589,31 +608,6 @@ public class FTDISerialDevice extends UsbSerialDevice
}
}
}
// Copy data without FTDI headers
private 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++;
}
}
}
}
@Override
@ -658,7 +652,7 @@ public class FTDISerialDevice extends UsbSerialDevice
if(numberBytes > 2) // Data received
{
byte[] newBuffer = this.ftdiUtilities.adaptArray(tempBuffer);
byte[] newBuffer = adaptArray(tempBuffer);
System.arraycopy(newBuffer, 0, buffer, 0, buffer.length);
int p = numberBytes / 64;

Wyświetl plik

@ -331,7 +331,7 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
if(data.length > 2)
{
data = ((FTDISerialDevice) usbSerialDevice).ftdiUtilities.adaptArray(data);
data = FTDISerialDevice.adaptArray(data);
onReceivedData(data);
}
}else
@ -425,7 +425,7 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
if(dataReceived.length > 2)
{
dataReceived = ((FTDISerialDevice) usbSerialDevice).ftdiUtilities.adaptArray(dataReceived);
dataReceived = FTDISerialDevice.adaptArray(dataReceived);
onReceivedData(dataReceived);
}
}else

Wyświetl plik

@ -0,0 +1,49 @@
package com.felhr.usbserial;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.Arrays;
@RunWith(JUnit4.class)
public class FTDISerialDeviceTest {
@Test
public void adaptEmptyByteArray() {
byte[] onlyHeaders = {1, 2};
byte[] adapted = FTDISerialDevice.adaptArray(onlyHeaders);
Assert.assertEquals("Should be empty", 0, adapted.length);
byte[] adaptAgain = FTDISerialDevice.adaptArray(onlyHeaders);
Assert.assertSame("Should be the same instance of empty array", adapted, adaptAgain);
}
@Test
public void withHeaders() {
byte[] withHeaders = {1, 2, 3, 4, 5, 6};
byte[] wanted = {3,4,5,6};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void fullWithHeaders() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
byte[] wanted = Arrays.copyOfRange(withHeaders, 2, 64);
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void testMultipleFull() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
byte[] wanted = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void testMultiplePartial() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62};
byte[] wanted = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
}