Add read() and write() with length argument

To reduce array copy
pull/544/head
wh201906 2023-11-05 20:38:14 +08:00
rodzic 880c0070cb
commit 1db6c393a8
Nie znaleziono w bazie danych klucza dla tego podpisu
3 zmienionych plików z 63 dodań i 16 usunięć

Wyświetl plik

@ -169,16 +169,23 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
@Override
public int read(final byte[] dest, final int timeout) throws IOException {
return read(dest, timeout, true);
if(dest.length <= 0) {
throw new IllegalArgumentException("Read buffer too small");
}
return read(dest, dest.length, timeout);
}
protected int read(final byte[] dest, final int timeout, boolean testConnection) throws IOException {
@Override
public int read(final byte[] dest, final int length, final int timeout) throws IOException {return read(dest, length, timeout, true);}
protected int read(final byte[] dest, int length, final int timeout, boolean testConnection) throws IOException {
if(mConnection == null || mUsbRequest == null) {
throw new IOException("Connection closed");
}
if(dest.length <= 0) {
throw new IllegalArgumentException("Read buffer to small");
if(length <= 0) {
throw new IllegalArgumentException("Read length too small");
}
length = Math.min(length, dest.length);
final int nread;
if (timeout != 0) {
// bulkTransfer will cause data loss with short timeout + high baud rates + continuous transfer
@ -190,7 +197,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
// /system/lib64/libandroid_runtime.so (android_hardware_UsbDeviceConnection_request_wait(_JNIEnv*, _jobject*, long)+84)
// data loss / crashes were observed with timeout up to 200 msec
long endTime = testConnection ? MonotonicClock.millis() + timeout : 0;
int readMax = Math.min(dest.length, MAX_READ_SIZE);
int readMax = Math.min(length, MAX_READ_SIZE);
nread = mConnection.bulkTransfer(mReadEndpoint, dest, readMax, timeout);
// Android error propagation is improvable:
// nread == -1 can be: timeout, connection lost, buffer to small, ???
@ -198,8 +205,8 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
testConnection();
} else {
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!mUsbRequest.queue(buf, dest.length)) {
final ByteBuffer buf = ByteBuffer.wrap(dest, 0, length);
if (!mUsbRequest.queue(buf, length)) {
throw new IOException("Queueing USB request failed");
}
final UsbRequest response = mConnection.requestWait();
@ -217,14 +224,18 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
}
@Override
public void write(final byte[] src, final int timeout) throws IOException {
public void write(byte[] src, int timeout) throws IOException {write(src, src.length, timeout);}
@Override
public void write(final byte[] src, int length, final int timeout) throws IOException {
int offset = 0;
final long endTime = (timeout == 0) ? 0 : (MonotonicClock.millis() + timeout);
length = Math.min(length, src.length);
if(mConnection == null) {
throw new IOException("Connection closed");
}
while (offset < src.length) {
while (offset < length) {
int requestTimeout;
final int requestLength;
final int actualLength;
@ -235,7 +246,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
if (mWriteBuffer == null) {
mWriteBuffer = new byte[mWriteEndpoint.getMaxPacketSize()];
}
requestLength = Math.min(src.length - offset, mWriteBuffer.length);
requestLength = Math.min(length - offset, mWriteBuffer.length);
if (offset == 0) {
writeBuffer = src;
} else {
@ -257,7 +268,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
}
}
if (DEBUG) {
Log.d(TAG, "Wrote " + actualLength + "/" + requestLength + " offset " + offset + "/" + src.length + " timeout " + requestTimeout);
Log.d(TAG, "Wrote " + actualLength + "/" + requestLength + " offset " + offset + "/" + length + " timeout " + requestTimeout);
}
if (actualLength <= 0) {
if (timeout != 0 && MonotonicClock.millis() >= endTime) {
@ -265,7 +276,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
ex.bytesTransferred = offset;
throw ex;
} else {
throw new IOException("Error writing " + requestLength + " bytes at offset " + offset + " of total " + src.length);
throw new IOException("Error writing " + requestLength + " bytes at offset " + offset + " of total " + length);
}
}
offset += actualLength;

Wyświetl plik

@ -139,24 +139,37 @@ public class FtdiSerialDriver implements UsbSerialDriver {
}
@Override
public int read(final byte[] dest, final int timeout) throws IOException {
public int read(final byte[] dest, final int timeout) throws IOException
{
if(dest.length <= READ_HEADER_LENGTH) {
throw new IllegalArgumentException("Read buffer to small");
throw new IllegalArgumentException("Read buffer too small");
// could allocate larger buffer, including space for 2 header bytes, but this would
// result in buffers not being 64 byte aligned any more, causing data loss at continuous
// data transfer at high baud rates when buffers are fully filled.
}
return read(dest, dest.length, timeout);
}
@Override
public int read(final byte[] dest, int length, final int timeout) throws IOException {
if(length <= READ_HEADER_LENGTH) {
throw new IllegalArgumentException("Read length too small");
// could allocate larger buffer, including space for 2 header bytes, but this would
// result in buffers not being 64 byte aligned any more, causing data loss at continuous
// data transfer at high baud rates when buffers are fully filled.
}
length = Math.min(length, dest.length);
int nread;
if (timeout != 0) {
long endTime = MonotonicClock.millis() + timeout;
do {
nread = super.read(dest, Math.max(1, (int)(endTime - MonotonicClock.millis())), false);
nread = super.read(dest, length, Math.max(1, (int)(endTime - MonotonicClock.millis())), false);
} while (nread == READ_HEADER_LENGTH && MonotonicClock.millis() < endTime);
if(nread <= 0 && MonotonicClock.millis() < endTime)
testConnection();
} else {
do {
nread = super.read(dest, timeout);
nread = super.read(dest, length, timeout);
} while (nread == READ_HEADER_LENGTH);
}
return readFilter(dest, nread);

Wyświetl plik

@ -122,6 +122,17 @@ public interface UsbSerialPort extends Closeable {
*/
int read(final byte[] dest, final int timeout) throws IOException;
/**
* Reads bytes with specified length into the destination buffer.
*
* @param dest the destination byte buffer
* @param length the maximum length of the data to read
* @param timeout the timeout for reading in milliseconds, 0 is infinite
* @return the actual number of bytes read
* @throws IOException if an error occurred during reading
*/
int read(final byte[] dest, int length, final int timeout) throws IOException;
/**
* Writes as many bytes as possible from the source buffer.
*
@ -133,6 +144,18 @@ public interface UsbSerialPort extends Closeable {
*/
void write(final byte[] src, final int timeout) throws IOException;
/**
* Writes bytes with specified length from the source buffer.
*
* @param src the source byte buffer
* @param length the length of the data to write
* @param timeout the timeout for writing in milliseconds, 0 is infinite
* @throws SerialTimeoutException if timeout reached before sending all data.
* ex.bytesTransferred may contain bytes transferred
* @throws IOException if an error occurred during writing
*/
void write(final byte[] src, int length, final int timeout) throws IOException;
/**
* Sets various serial port parameters.
*