Skip to content

Commit d10cd04

Browse files
committed
USB driver patch
Refactored SerialInputOutputManager: - Implemented multiple read buffers to improve USB reading efficiency and reduce latency. - Used separate threads for reading and writing, enhancing concurrency and performance. - Removed read timeouts, as they are not necessary for event-driven data reading. These changes enhance the responsiveness, reliability, and robustness of USB communication.
1 parent cc2a0e5 commit d10cd04

File tree

5 files changed

+201
-147
lines changed

5 files changed

+201
-147
lines changed

android-src/KV4PHT/app/src/main/java/com/vagell/kv4pht/radio/RadioAudioService.java

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,8 @@ public void onRunError(Exception e) {
931931
}
932932
});
933933
usbIoManager.setWriteBufferSize(90000); // Must be large enough that ESP32 can take its time accepting our bytes without overrun.
934-
usbIoManager.setReadTimeout(1000); // Must not be 0 (infinite) or it may block on read() until a write() occurs.
935-
usbIoManager.start();
934+
usbIoManager.setReadBufferSize(1024/4); // Must not be 0 (infinite) or it may block on read() until a write() occurs.
935+
usbIoManager.setReadBufferCount(16*4);
936936
checkedFirmwareVersion = false;
937937

938938
Log.d("DEBUG", "Connected to ESP32.");
@@ -1217,43 +1217,7 @@ public synchronized void sendBytesToESP32(byte[] newBytes) {
12171217
Log.d("DEBUG", "Warning: Attempted to send bytes to ESP32 while in the process of flashing a new firmware.");
12181218
return;
12191219
}
1220-
1221-
int usbRetries = 0;
1222-
try {
1223-
// usbIoManager.writeAsync(newBytes); // On MCUs like the ESP32 S2 this causes USB failures with concurrent USB rx/tx.
1224-
int bytesWritten = 0;
1225-
int totalBytes = newBytes.length;
1226-
final int MAX_BYTES_PER_USB_WRITE = 128;
1227-
do {
1228-
try {
1229-
byte[] arrayPart = Arrays.copyOfRange(newBytes, bytesWritten, Math.min(bytesWritten + MAX_BYTES_PER_USB_WRITE, totalBytes));
1230-
serialPort.write(arrayPart, 200);
1231-
bytesWritten += MAX_BYTES_PER_USB_WRITE;
1232-
usbRetries = 0;
1233-
} catch (SerialTimeoutException ste) {
1234-
// Do nothing, we'll try again momentarily. ESP32's serial buffer may be full.
1235-
usbRetries++;
1236-
Log.d("DEBUG", "usbRetries: " + usbRetries);
1237-
}
1238-
} while (bytesWritten < totalBytes && usbRetries < 10);
1239-
// Log.d("DEBUG", "Wrote data: " + Arrays.toString(newBytes));
1240-
} catch (Exception e) {
1241-
e.printStackTrace();
1242-
try {
1243-
serialPort.close();
1244-
} catch (Exception ex) {
1245-
// Ignore. We did our best to close it!
1246-
}
1247-
try {
1248-
Thread.sleep(1000);
1249-
} catch (InterruptedException ex) {
1250-
// Ignore. This should only happen if the app is paused in this brief moment between USB retries, not a serious issue.
1251-
}
1252-
findESP32Device(); // Attempt to reconnect after the brief pause above.
1253-
}
1254-
if (usbRetries == 10) {
1255-
Log.d("DEBUG", "sendBytesToESP32: Connected to ESP32 via USB serial, but could not send data after 10 retries.");
1256-
}
1220+
usbIoManager.writeAsync(newBytes);
12571221
}
12581222

12591223
public static UsbSerialPort getUsbSerialPort() {

android-src/KV4PHT/usbSerialForAndroid/src/androidTest/java/com/hoho/android/usbserial/DeviceTest.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,6 @@ private int readSpeedInt(int writeSeconds, int readBufferSize, int readTimeout)
12061206
writeAhead = 50;
12071207

12081208
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_IOMANAGER_START));
1209-
usb.ioManager.setReadTimeout(readTimeout);
12101209
if(readBufferSize > 0)
12111210
usb.ioManager.setReadBufferSize(readBufferSize);
12121211
usb.ioManager.start();
@@ -1383,9 +1382,6 @@ public void IoManager() throws Exception {
13831382
usb.ioManager = new SerialInputOutputManager(usb.serialPort, usb);
13841383
assertEquals(usb, usb.ioManager.getListener());
13851384

1386-
assertEquals(0, usb.ioManager.getReadTimeout());
1387-
usb.ioManager.setReadTimeout(10);
1388-
assertEquals(10, usb.ioManager.getReadTimeout());
13891385
assertEquals(0, usb.ioManager.getWriteTimeout());
13901386
usb.ioManager.setWriteTimeout(11);
13911387
assertEquals(11, usb.ioManager.getWriteTimeout());
@@ -1399,7 +1395,6 @@ public void IoManager() throws Exception {
13991395

14001396
usb.ioManager.setReadBufferSize(usb.ioManager.getReadBufferSize());
14011397
usb.ioManager.setWriteBufferSize(usb.ioManager.getWriteBufferSize());
1402-
usb.ioManager.setReadTimeout(usb.ioManager.getReadTimeout());
14031398
usb.ioManager.setWriteTimeout(usb.ioManager.getWriteTimeout());
14041399
usb.close();
14051400

@@ -1416,19 +1411,14 @@ public void IoManager() throws Exception {
14161411
} catch (IllegalStateException ignored) {
14171412
}
14181413
try {
1419-
usb.ioManager.run();
1414+
usb.ioManager.start();
14201415
fail("already running error expected");
14211416
} catch (IllegalStateException ignored) {
14221417
}
14231418
try {
14241419
usb.ioManager.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
14251420
fail("setThreadPriority IllegalStateException expected");
14261421
} catch (IllegalStateException ignored) {}
1427-
try {
1428-
usb.ioManager.setReadTimeout(20);
1429-
fail("setReadTimeout IllegalStateException expected");
1430-
} catch (IllegalStateException ignored) {}
1431-
assertEquals(0, usb.ioManager.getReadTimeout());
14321422
usb.ioManager.setWriteTimeout(21);
14331423
assertEquals(21, usb.ioManager.getWriteTimeout());
14341424
usb.ioManager.setReadBufferSize(22);
@@ -1484,7 +1474,6 @@ public void IoManager() throws Exception {
14841474
usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
14851475
telnet.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
14861476
usb.ioManager.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
1487-
Executors.newSingleThreadExecutor().submit(usb.ioManager);
14881477
usb.waitForIoManagerStarted();
14891478
try {
14901479
usb.ioManager.start();
@@ -1514,15 +1503,13 @@ public void writeAsync() throws Exception {
15141503

15151504
// with timeout: write after timeout
15161505
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_IOMANAGER_START));
1517-
usb.ioManager.setReadTimeout(100);
15181506
usb.ioManager.start();
15191507
usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
15201508
telnet.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
15211509
usb.ioManager.writeAsync(buf);
15221510
usb.ioManager.writeAsync(buf);
15231511
data = telnet.read(2);
15241512
assertEquals(2, data.length);
1525-
usb.ioManager.setReadTimeout(200);
15261513
}
15271514

15281515
@Test

android-src/KV4PHT/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/CommonUsbSerialPort.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort {
3333
protected final UsbDevice mDevice;
3434
protected final int mPortNumber;
3535

36-
// non-null when open()
36+
@Override
37+
public UsbDeviceConnection getConnection() {
38+
return mConnection;
39+
}
40+
41+
// non-null when open()
3742
protected UsbDeviceConnection mConnection = null;
3843
protected UsbEndpoint mReadEndpoint;
3944
protected UsbEndpoint mWriteEndpoint;

android-src/KV4PHT/usbSerialForAndroid/src/main/java/com/hoho/android/usbserial/driver/UsbSerialPort.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,6 @@ enum ControlLine { RTS, CTS, DTR, DSR, CD, RI }
281281
*/
282282
boolean isOpen();
283283

284+
UsbDeviceConnection getConnection();
285+
284286
}

0 commit comments

Comments
 (0)