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 @Override
public int read(final byte[] dest, final int timeout) throws IOException { 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) { if(mConnection == null || mUsbRequest == null) {
throw new IOException("Connection closed"); throw new IOException("Connection closed");
} }
if(dest.length <= 0) { if(length <= 0) {
throw new IllegalArgumentException("Read buffer to small"); throw new IllegalArgumentException("Read length too small");
} }
length = Math.min(length, dest.length);
final int nread; final int nread;
if (timeout != 0) { if (timeout != 0) {
// bulkTransfer will cause data loss with short timeout + high baud rates + continuous transfer // 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) // /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 // data loss / crashes were observed with timeout up to 200 msec
long endTime = testConnection ? MonotonicClock.millis() + timeout : 0; 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); nread = mConnection.bulkTransfer(mReadEndpoint, dest, readMax, timeout);
// Android error propagation is improvable: // Android error propagation is improvable:
// nread == -1 can be: timeout, connection lost, buffer to small, ??? // nread == -1 can be: timeout, connection lost, buffer to small, ???
@ -198,8 +205,8 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
testConnection(); testConnection();
} else { } else {
final ByteBuffer buf = ByteBuffer.wrap(dest); final ByteBuffer buf = ByteBuffer.wrap(dest, 0, length);
if (!mUsbRequest.queue(buf, dest.length)) { if (!mUsbRequest.queue(buf, length)) {
throw new IOException("Queueing USB request failed"); throw new IOException("Queueing USB request failed");
} }
final UsbRequest response = mConnection.requestWait(); final UsbRequest response = mConnection.requestWait();
@ -217,14 +224,18 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
} }
@Override @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; int offset = 0;
final long endTime = (timeout == 0) ? 0 : (MonotonicClock.millis() + timeout); final long endTime = (timeout == 0) ? 0 : (MonotonicClock.millis() + timeout);
length = Math.min(length, src.length);
if(mConnection == null) { if(mConnection == null) {
throw new IOException("Connection closed"); throw new IOException("Connection closed");
} }
while (offset < src.length) { while (offset < length) {
int requestTimeout; int requestTimeout;
final int requestLength; final int requestLength;
final int actualLength; final int actualLength;
@ -235,7 +246,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
if (mWriteBuffer == null) { if (mWriteBuffer == null) {
mWriteBuffer = new byte[mWriteEndpoint.getMaxPacketSize()]; mWriteBuffer = new byte[mWriteEndpoint.getMaxPacketSize()];
} }
requestLength = Math.min(src.length - offset, mWriteBuffer.length); requestLength = Math.min(length - offset, mWriteBuffer.length);
if (offset == 0) { if (offset == 0) {
writeBuffer = src; writeBuffer = src;
} else { } else {
@ -257,7 +268,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
} }
} }
if (DEBUG) { 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 (actualLength <= 0) {
if (timeout != 0 && MonotonicClock.millis() >= endTime) { if (timeout != 0 && MonotonicClock.millis() >= endTime) {
@ -265,7 +276,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
ex.bytesTransferred = offset; ex.bytesTransferred = offset;
throw ex; throw ex;
} else { } 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; offset += actualLength;

Wyświetl plik

@ -139,24 +139,37 @@ public class FtdiSerialDriver implements UsbSerialDriver {
} }
@Override @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) { 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 // 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 // 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. // 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; int nread;
if (timeout != 0) { if (timeout != 0) {
long endTime = MonotonicClock.millis() + timeout; long endTime = MonotonicClock.millis() + timeout;
do { 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); } while (nread == READ_HEADER_LENGTH && MonotonicClock.millis() < endTime);
if(nread <= 0 && MonotonicClock.millis() < endTime) if(nread <= 0 && MonotonicClock.millis() < endTime)
testConnection(); testConnection();
} else { } else {
do { do {
nread = super.read(dest, timeout); nread = super.read(dest, length, timeout);
} while (nread == READ_HEADER_LENGTH); } while (nread == READ_HEADER_LENGTH);
} }
return readFilter(dest, nread); 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; 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. * 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; 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. * Sets various serial port parameters.
* *