1
0
mirror of https://github.com/mik3y/usb-serial-for-android.git synced 2026-10-13 22:51:42 +00:00

CH34x flow control

the tests look like the CH34x only partially supports flow control
CTS ok: writing data correctly blocks if CTS is unset.
RTS not ok: when not reading data (fast enough), RTS is not unset on buffer full
This commit is contained in:
kai-morich
2026-10-06 21:48:29 +02:00
parent 377be3a2bd
commit 6a9c61f1fa
4 changed files with 49 additions and 20 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ project.afterEvaluate {
// values used for local maven repo, jitpack uses github release:
groupId 'com.github.mik3y'
artifactId 'usb-serial-for-android'
version '3.9.1beta'
version '3.12.0beta'
}
}
}
@@ -2185,6 +2185,7 @@ public class DeviceTest {
boolean outputLineReadable = false; // getControlLines returns configured value
FlowControl_OutputLineLocked outputLineLocked = FlowControl_OutputLineLocked.FALSE;
boolean outputLineSet = false;
boolean inputFlowControl = true;
if(usb.serialDriver instanceof ProlificSerialDriver) {
outputLineSet = true; // line set to 'true' on setFlowControl
outputLineLocked = FlowControl_OutputLineLocked.TRUE; // setRts/Dtr has no effect
@@ -2197,7 +2198,9 @@ public class DeviceTest {
if(usb.serialDriver instanceof FtdiSerialDriver) {
outputLineLocked = FlowControl_OutputLineLocked.ON_BUFFER_FULL;
}
if(usb.serialDriver instanceof Ch34xSerialDriver) {
inputFlowControl = false;
}
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
telnet.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);
usb.setParameters(115200, 8, 1, UsbSerialPort.PARITY_NONE);
@@ -2313,23 +2316,25 @@ public class DeviceTest {
}
}
new NoRead().run();
if (inputFlowControl) {
new NoRead().run();
// no read -> buffer full -> RTS/DTR off -> output line locked
if(outputLineLocked != FlowControl_OutputLineLocked.TRUE) {
assertTrue(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
for(i = 0; i < 120 && usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR); i++) {
telnet.write(buf64);
Thread.sleep(controlLineWait);
}
assertFalse(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
if(m) usb.serialPort.setRTS(true); else usb.serialPort.setDTR(true);
Thread.sleep(controlLineWait);
if(outputLineLocked == FlowControl_OutputLineLocked.ON_BUFFER_FULL)
assertFalse(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
else
// no read -> buffer full -> RTS/DTR off -> output line locked
if (outputLineLocked != FlowControl_OutputLineLocked.TRUE) {
assertTrue(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
data = usb.read(-1, i*64, 100);
for (i = 0; i < 120 && usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR); i++) {
telnet.write(buf64);
Thread.sleep(controlLineWait);
}
assertFalse(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR)); // RTS not unset on CH34x
if (m) usb.serialPort.setRTS(true); else usb.serialPort.setDTR(true);
Thread.sleep(controlLineWait);
if (outputLineLocked == FlowControl_OutputLineLocked.ON_BUFFER_FULL)
assertFalse(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
else
assertTrue(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
data = usb.read(-1, i * 64, 100);
}
}
// mode retained over close
@@ -2341,7 +2346,8 @@ public class DeviceTest {
assertEquals(flowControl, usb.serialPort.getFlowControl());
assertTrue(m ? usb.serialPort.getRTS() : usb.serialPort.getDTR());
assertTrue(usb.serialPort.getControlLines().contains(m ? ControlLine.CTS : ControlLine.DSR));
new NoRead().run();
if (inputFlowControl)
new NoRead().run();
}
@Test
@@ -135,8 +135,9 @@ public class UsbWrapper implements SerialInputOutputManager.Listener {
} else if (serialDriver instanceof Ch34xSerialDriver) {
outputLinesSupported = true;
inputLinesSupported = true;
if(serialDriver.getDevice().getProductId() == UsbId.QINHENG_CH340)
inputLinesConnected = true; // I only have 74LS138 connected at CH340, not connected at CH341A
inputLinesConnected = true;
if(serialDriver.getDevice().getProductId() == UsbId.QINHENG_CH341A)
inputLinesOnlyRtsCts = true;
} else if (serialDriver instanceof CdcAcmSerialDriver) {
outputLinesSupported = true;
inputLinesSupported = true;
@@ -101,6 +101,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
initialize();
setBaudRate(DEFAULT_BAUD_RATE);
setFlowControl(mFlowControl);
}
@Override
@@ -357,6 +358,27 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
return EnumSet.allOf(ControlLine.class);
}
@Override
public void setFlowControl(FlowControl flowControl) throws IOException {
if (flowControl == FlowControl.RTS_CTS) {
if (controlOut(0x9a, 0x2727, 0x0101) < 0) {
throw new IOException("Error setting flow control");
}
} else if (flowControl == FlowControl.NONE) {
if (controlOut(0x9a, 0x2727, 0x0000) < 0) {
throw new IOException("Error setting flow control");
}
} else {
throw new UnsupportedOperationException("Unsupported flow control: " + flowControl);
}
mFlowControl = flowControl;
}
@Override
public EnumSet<FlowControl> getSupportedFlowControl() {
return EnumSet.of(FlowControl.NONE, FlowControl.RTS_CTS);
}
@Override
public void setBreak(boolean value) throws IOException {
byte[] req = new byte[2];