mirror of
https://github.com/mik3y/usb-serial-for-android.git
synced 2026-08-11 08:22:52 +00:00
support CDC input control lines
This commit is contained in:
@@ -165,7 +165,7 @@ some other device specific drivers
|
|||||||
* Chrome OS CCD (Closed Case Debugging)
|
* Chrome OS CCD (Closed Case Debugging)
|
||||||
|
|
||||||
and devices implementing the generic CDC/ACM protocol like
|
and devices implementing the generic CDC/ACM protocol like
|
||||||
* Qinheng CH9102
|
* Qinheng CH343, CH9102
|
||||||
* Microchip MCP2221
|
* Microchip MCP2221
|
||||||
* Arduino using ATmega32U4
|
* Arduino using ATmega32U4
|
||||||
* Digispark using V-USB software USB
|
* Digispark using V-USB software USB
|
||||||
|
|||||||
+29
-24
@@ -510,21 +510,21 @@ public class DeviceTest {
|
|||||||
fail("invalid baudrate 1");
|
fail("invalid baudrate 1");
|
||||||
} catch (UnsupportedOperationException ignored) { // ch340
|
} catch (UnsupportedOperationException ignored) { // ch340
|
||||||
} catch (IOException ignored) { // cp2105 second port
|
} catch (IOException ignored) { // cp2105 second port
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
usb.setParameters(1<<31, 8, 1, UsbSerialPort.PARITY_NONE);
|
usb.setParameters(1<<30, 8, 1, UsbSerialPort.PARITY_NONE);
|
||||||
if (usb.serialDriver instanceof ProlificSerialDriver)
|
if (usb.serialDriver instanceof ProlificSerialDriver)
|
||||||
;
|
;
|
||||||
else if (usb.serialDriver instanceof Cp21xxSerialDriver)
|
else if (usb.serialDriver instanceof Cp21xxSerialDriver)
|
||||||
;
|
;
|
||||||
else if (usb.serialDriver instanceof CdcAcmSerialDriver)
|
else if (usb.serialDriver instanceof CdcAcmSerialDriver)
|
||||||
;
|
;
|
||||||
|
else if (usb.serialDriver instanceof Ch34xSerialDriver)
|
||||||
|
;
|
||||||
else
|
else
|
||||||
fail("invalid baudrate 2^31");
|
fail("invalid baudrate 2^30");
|
||||||
} catch (ArithmeticException ignored) { // ch340
|
} catch (UnsupportedOperationException ignored) { // ftdi
|
||||||
} catch (IOException ignored) { // cp2105 second port
|
} catch (IOException ignored) { // cp2105 second port
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int baudRate : new int[] {300, 2400, 19200, 115200} ) {
|
for(int baudRate : new int[] {300, 2400, 19200, 115200} ) {
|
||||||
@@ -1657,6 +1657,7 @@ public class DeviceTest {
|
|||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// CDC CH9143 only recovers from CH... commands with power toggle, so skip this combination
|
||||||
if(!(usb.serialDriver instanceof Ch34xSerialDriver)) {
|
if(!(usb.serialDriver instanceof Ch34xSerialDriver)) {
|
||||||
UsbDeviceConnection wrongDeviceConnection = usbManager.openDevice(usb.serialDriver.getDevice());
|
UsbDeviceConnection wrongDeviceConnection = usbManager.openDevice(usb.serialDriver.getDevice());
|
||||||
UsbSerialDriver wrongSerialDriver = new Ch34xSerialDriver(usb.serialDriver.getDevice());
|
UsbSerialDriver wrongSerialDriver = new Ch34xSerialDriver(usb.serialDriver.getDevice());
|
||||||
@@ -1795,7 +1796,8 @@ public class DeviceTest {
|
|||||||
supportedControlLines.add(ControlLine.DTR);
|
supportedControlLines.add(ControlLine.DTR);
|
||||||
}
|
}
|
||||||
if(usb.inputLinesSupported) {
|
if(usb.inputLinesSupported) {
|
||||||
supportedControlLines.add(ControlLine.CTS);
|
if(usb.inputLineCtsSupported)
|
||||||
|
supportedControlLines.add(ControlLine.CTS);
|
||||||
supportedControlLines.add(ControlLine.DSR);
|
supportedControlLines.add(ControlLine.DSR);
|
||||||
supportedControlLines.add(ControlLine.CD);
|
supportedControlLines.add(ControlLine.CD);
|
||||||
supportedControlLines.add(ControlLine.RI);
|
supportedControlLines.add(ControlLine.RI);
|
||||||
@@ -1823,16 +1825,16 @@ public class DeviceTest {
|
|||||||
|
|
||||||
// control lines reset on initial open
|
// control lines reset on initial open
|
||||||
data = "none".getBytes();
|
data = "none".getBytes();
|
||||||
assertEquals(usb.inputLinesConnected && !usb.inputLinesOnlyRtsCts
|
assertEquals(usb.inputLinesConnected && !usb.inputLinesOnlyRtsCts && usb.inputLineCtsSupported
|
||||||
? EnumSet.of(ControlLine.RI)
|
? EnumSet.of(ControlLine.RI)
|
||||||
: EnumSet.noneOf(ControlLine.class),
|
: EnumSet.noneOf(ControlLine.class),
|
||||||
usb.serialPort.getControlLines());
|
usb.serialPort.getControlLines());
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.FALSE));
|
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.FALSE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLineCtsSupported ? inputLineFalse : null));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.FALSE : inputLineTrue));
|
assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(usb.inputLinesOnlyRtsCts || !usb.inputLineCtsSupported ? Boolean.FALSE : inputLineTrue));
|
||||||
telnet.write(data);
|
telnet.write(data);
|
||||||
assertThat(Arrays.toString(data), usb.read(4), equalTo(data));
|
assertThat(Arrays.toString(data), usb.read(4), equalTo(data));
|
||||||
usb.write(data);
|
usb.write(data);
|
||||||
@@ -1841,12 +1843,12 @@ public class DeviceTest {
|
|||||||
data = "rts ".getBytes();
|
data = "rts ".getBytes();
|
||||||
usb.serialPort.setRTS(true);
|
usb.serialPort.setRTS(true);
|
||||||
Thread.sleep(sleep);
|
Thread.sleep(sleep);
|
||||||
assertEquals(usb.inputLinesConnected
|
assertEquals(usb.inputLinesConnected & usb.inputLineCtsSupported
|
||||||
? EnumSet.of(ControlLine.RTS, ControlLine.CTS)
|
? EnumSet.of(ControlLine.RTS, ControlLine.CTS)
|
||||||
: EnumSet.of(ControlLine.RTS),
|
: EnumSet.of(ControlLine.RTS),
|
||||||
usb.serialPort.getControlLines());
|
usb.serialPort.getControlLines());
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.TRUE));
|
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.TRUE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(inputLineTrue));
|
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLineCtsSupported ? inputLineTrue : null));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
||||||
@@ -1859,14 +1861,15 @@ public class DeviceTest {
|
|||||||
data = "both".getBytes();
|
data = "both".getBytes();
|
||||||
usb.serialPort.setDTR(true);
|
usb.serialPort.setDTR(true);
|
||||||
Thread.sleep(sleep);
|
Thread.sleep(sleep);
|
||||||
assertEquals(usb.inputLinesOnlyRtsCts
|
if(usb.inputLinesOnlyRtsCts) {
|
||||||
? EnumSet.of(ControlLine.RTS, ControlLine.DTR, ControlLine.CTS)
|
assertEquals(EnumSet.of(ControlLine.RTS, ControlLine.DTR, ControlLine.CTS), usb.serialPort.getControlLines());
|
||||||
: usb.inputLinesConnected
|
} else if(usb.inputLinesConnected) {
|
||||||
? EnumSet.of(ControlLine.RTS, ControlLine.DTR, ControlLine.CD)
|
assertEquals(EnumSet.of(ControlLine.RTS, ControlLine.DTR, ControlLine.CD), usb.serialPort.getControlLines());
|
||||||
: EnumSet.of(ControlLine.RTS, ControlLine.DTR),
|
} else {
|
||||||
usb.serialPort.getControlLines());
|
assertEquals(EnumSet.of(ControlLine.RTS, ControlLine.DTR), usb.serialPort.getControlLines());
|
||||||
|
}
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.TRUE));
|
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.TRUE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.TRUE : inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLineCtsSupported ? (usb.inputLinesOnlyRtsCts ? Boolean.TRUE : inputLineFalse) : null));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.TRUE));
|
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.TRUE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.FALSE : inputLineTrue));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.FALSE : inputLineTrue));
|
||||||
@@ -1884,7 +1887,7 @@ public class DeviceTest {
|
|||||||
: EnumSet.of(ControlLine.DTR),
|
: EnumSet.of(ControlLine.DTR),
|
||||||
usb.serialPort.getControlLines());
|
usb.serialPort.getControlLines());
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.FALSE));
|
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(Boolean.FALSE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLineCtsSupported ? inputLineFalse : null));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.TRUE));
|
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.TRUE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.FALSE : inputLineTrue));
|
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(usb.inputLinesOnlyRtsCts ? Boolean.FALSE : inputLineTrue));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
||||||
@@ -1905,10 +1908,10 @@ public class DeviceTest {
|
|||||||
|
|
||||||
EnumSet<ControlLine> retainedControlLines = EnumSet.noneOf(ControlLine.class);
|
EnumSet<ControlLine> retainedControlLines = EnumSet.noneOf(ControlLine.class);
|
||||||
if(outputRetained) retainedControlLines.add(ControlLine.RTS);
|
if(outputRetained) retainedControlLines.add(ControlLine.RTS);
|
||||||
if(inputRetained) retainedControlLines.add(ControlLine.CTS);
|
if(inputRetained && usb.inputLineCtsSupported) retainedControlLines.add(ControlLine.CTS);
|
||||||
assertEquals(retainedControlLines, usb.serialPort.getControlLines());
|
assertEquals(retainedControlLines, usb.serialPort.getControlLines());
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(outputRetained));
|
assertThat(usb.getControlLine(usb.serialPort::getRTS), equalTo(outputRetained));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(inputRetained ? inputLineTrue : inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCTS), equalTo(usb.inputLineCtsSupported ? (inputRetained ? inputLineTrue : inputLineFalse) : null));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
assertThat(usb.getControlLine(usb.serialPort::getDTR), equalTo(Boolean.FALSE));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getDSR), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
||||||
@@ -1958,7 +1961,8 @@ public class DeviceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (usb.serialDriver instanceof ProlificSerialDriver) {
|
if (usb.serialDriver instanceof ProlificSerialDriver
|
||||||
|
|| usb.serialDriver instanceof CdcAcmSerialDriver) {
|
||||||
for(int i = 0; i < 10; i++) { // can take some time until background thread fails
|
for(int i = 0; i < 10; i++) { // can take some time until background thread fails
|
||||||
usb.serialPort.getRI();
|
usb.serialPort.getRI();
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
@@ -2413,8 +2417,9 @@ public class DeviceTest {
|
|||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if(usb.serialDriver instanceof ProlificSerialDriver)
|
if(usb.serialDriver instanceof ProlificSerialDriver
|
||||||
Thread.sleep(600); // wait for background thread
|
|| usb.serialDriver instanceof CdcAcmSerialDriver)
|
||||||
|
Thread.sleep(600); // wait for background thread to fail
|
||||||
usb.serialPort.getRI();
|
usb.serialPort.getRI();
|
||||||
fail("getRI error expected");
|
fail("getRI error expected");
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
|||||||
+10
-5
@@ -65,6 +65,7 @@ public class UsbWrapper implements SerialInputOutputManager.Listener {
|
|||||||
public boolean inputLinesSupported;
|
public boolean inputLinesSupported;
|
||||||
public boolean inputLinesConnected;
|
public boolean inputLinesConnected;
|
||||||
public boolean inputLinesOnlyRtsCts;
|
public boolean inputLinesOnlyRtsCts;
|
||||||
|
public boolean inputLineCtsSupported;
|
||||||
public int writePacketSize = -1;
|
public int writePacketSize = -1;
|
||||||
public int writeBufferSize = -1;
|
public int writeBufferSize = -1;
|
||||||
public int readBufferSize = -1;
|
public int readBufferSize = -1;
|
||||||
@@ -111,7 +112,8 @@ public class UsbWrapper implements SerialInputOutputManager.Listener {
|
|||||||
isCdcAcmCh343 = serialDriver.getDevice().getVendorId() == UsbId.VENDOR_QINHENG && serialDriver.getDevice().getProductId() == 0x55D3;
|
isCdcAcmCh343 = serialDriver.getDevice().getVendorId() == UsbId.VENDOR_QINHENG && serialDriver.getDevice().getProductId() == 0x55D3;
|
||||||
|
|
||||||
// output lines are supported by all common drivers
|
// output lines are supported by all common drivers
|
||||||
// input lines are supported by all common drivers except CDC
|
// input lines are supported by all common drivers, but only partly by CDC
|
||||||
|
inputLineCtsSupported = true;
|
||||||
if (serialDriver instanceof FtdiSerialDriver) {
|
if (serialDriver instanceof FtdiSerialDriver) {
|
||||||
outputLinesSupported = true;
|
outputLinesSupported = true;
|
||||||
inputLinesSupported = true;
|
inputLinesSupported = true;
|
||||||
@@ -137,6 +139,10 @@ public class UsbWrapper implements SerialInputOutputManager.Listener {
|
|||||||
inputLinesConnected = true; // I only have 74LS138 connected at CH340, not connected at CH341A
|
inputLinesConnected = true; // I only have 74LS138 connected at CH340, not connected at CH341A
|
||||||
} else if (serialDriver instanceof CdcAcmSerialDriver) {
|
} else if (serialDriver instanceof CdcAcmSerialDriver) {
|
||||||
outputLinesSupported = true;
|
outputLinesSupported = true;
|
||||||
|
inputLinesSupported = true;
|
||||||
|
if(isCdcAcmCh343)
|
||||||
|
inputLinesConnected = true;
|
||||||
|
inputLineCtsSupported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialDriver instanceof Cp21xxSerialDriver) {
|
if (serialDriver instanceof Cp21xxSerialDriver) {
|
||||||
@@ -322,10 +328,9 @@ public class UsbWrapper implements SerialInputOutputManager.Listener {
|
|||||||
|
|
||||||
public void setParameters(int baudRate, int dataBits, int stopBits, @UsbSerialPort.Parity int parity) throws IOException, InterruptedException {
|
public void setParameters(int baudRate, int dataBits, int stopBits, @UsbSerialPort.Parity int parity) throws IOException, InterruptedException {
|
||||||
serialPort.setParameters(baudRate, dataBits, stopBits, parity);
|
serialPort.setParameters(baudRate, dataBits, stopBits, parity);
|
||||||
if(serialDriver instanceof CdcAcmSerialDriver)
|
//if(serialDriver instanceof CdcAcmSerialDriver)
|
||||||
Thread.sleep(10); // arduino_leonardeo_bridge.ini needs some time
|
//Thread.sleep(10); // arduino_leonardeo_bridge.ini needs some time
|
||||||
else
|
Thread.sleep(1);
|
||||||
Thread.sleep(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return TRUE/FALSE/null instead of true/false/<throw UnsupportedOperationException> */
|
/* return TRUE/FALSE/null instead of true/false/<throw UnsupportedOperationException> */
|
||||||
|
|||||||
+98
-1
@@ -13,10 +13,12 @@ import android.hardware.usb.UsbInterface;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.hoho.android.usbserial.util.HexDump;
|
import com.hoho.android.usbserial.util.HexDump;
|
||||||
|
import com.hoho.android.usbserial.util.MonotonicClock;
|
||||||
import com.hoho.android.usbserial.util.UsbUtils;
|
import com.hoho.android.usbserial.util.UsbUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -99,6 +101,19 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
private static final int SET_CONTROL_LINE_STATE = 0x22;
|
private static final int SET_CONTROL_LINE_STATE = 0x22;
|
||||||
private static final int SEND_BREAK = 0x23;
|
private static final int SEND_BREAK = 0x23;
|
||||||
|
|
||||||
|
private static final int NOTIFICATION_REQUEST_TYPE = 0xA1;
|
||||||
|
private static final int SERIAL_STATE = 0x20;
|
||||||
|
private static final int SERIAL_STATE_PACKET_SIZE = 10;
|
||||||
|
private static final int SERIAL_STATE_FLAG_CD = 0x01;
|
||||||
|
private static final int SERIAL_STATE_FLAG_DSR = 0x02;
|
||||||
|
private static final int SERIAL_STATE_FLAG_RI = 0x08;
|
||||||
|
|
||||||
|
private volatile int mSerialState = 0;
|
||||||
|
private volatile Thread mReadControlLinesThread = null;
|
||||||
|
private final Object mReadControlLinesThreadLock = new Object();
|
||||||
|
private boolean mStopReadControlLinesThread = false;
|
||||||
|
private Exception mReadControlLinesException = null;
|
||||||
|
|
||||||
public CdcAcmSerialPort(UsbDevice device, int portNumber) {
|
public CdcAcmSerialPort(UsbDevice device, int portNumber) {
|
||||||
super(device, portNumber);
|
super(device, portNumber);
|
||||||
}
|
}
|
||||||
@@ -260,9 +275,71 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readControlLinesThreadFunction() {
|
||||||
|
try {
|
||||||
|
byte[] buffer = new byte[Math.max(SERIAL_STATE_PACKET_SIZE, mControlEndpoint.getMaxPacketSize())];
|
||||||
|
while (!mStopReadControlLinesThread) {
|
||||||
|
long endTime = MonotonicClock.millis() + 500;
|
||||||
|
int readBytesCount = mConnection.bulkTransfer(mControlEndpoint, buffer, buffer.length, 500);
|
||||||
|
if (readBytesCount == -1) {
|
||||||
|
testConnection(MonotonicClock.millis() < endTime);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (readBytesCount != SERIAL_STATE_PACKET_SIZE) continue;
|
||||||
|
if (buffer[0] != (byte)NOTIFICATION_REQUEST_TYPE) continue;
|
||||||
|
if (buffer[1] != SERIAL_STATE) continue;
|
||||||
|
int index = ((buffer[5] & 0xff) << 8) | (buffer[4] & 0xff);
|
||||||
|
if (index != mControlIndex) continue;
|
||||||
|
int payloadLength = ((buffer[7] & 0xff) << 8) | (buffer[6] & 0xff);
|
||||||
|
if (payloadLength < 2) continue;
|
||||||
|
mSerialState = ((buffer[9] & 0xff) << 8) | (buffer[8] & 0xff);
|
||||||
|
Log.d(TAG, "control line state " + Arrays.toString(buffer));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (isOpen()) {
|
||||||
|
mReadControlLinesException = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSerialState() throws IOException {
|
||||||
|
if ((mReadControlLinesThread == null) && (mReadControlLinesException == null)) {
|
||||||
|
synchronized (mReadControlLinesThreadLock) {
|
||||||
|
if (mReadControlLinesThread == null) {
|
||||||
|
mSerialState = 0;
|
||||||
|
mReadControlLinesThread = new Thread(this::readControlLinesThreadFunction);
|
||||||
|
mReadControlLinesThread.setDaemon(true);
|
||||||
|
mReadControlLinesThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exception readControlLinesException = mReadControlLinesException;
|
||||||
|
if (readControlLinesException != null) {
|
||||||
|
mReadControlLinesException = null;
|
||||||
|
throw new IOException(readControlLinesException);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mSerialState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void closeInt() {
|
protected void closeInt() {
|
||||||
try {
|
try {
|
||||||
|
synchronized (mReadControlLinesThreadLock) {
|
||||||
|
if (mReadControlLinesThread != null) {
|
||||||
|
try {
|
||||||
|
mStopReadControlLinesThread = true;
|
||||||
|
mReadControlLinesThread.join();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "An error occurred while waiting for control line read thread", e);
|
||||||
|
}
|
||||||
|
mStopReadControlLinesThread = false;
|
||||||
|
mReadControlLinesThread = null;
|
||||||
|
mReadControlLinesException = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
mConnection.releaseInterface(mControlInterface);
|
mConnection.releaseInterface(mControlInterface);
|
||||||
mConnection.releaseInterface(mDataInterface);
|
mConnection.releaseInterface(mDataInterface);
|
||||||
} catch(Exception ignored) {}
|
} catch(Exception ignored) {}
|
||||||
@@ -320,6 +397,21 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
return mRts;
|
return mRts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getCD() throws IOException {
|
||||||
|
return (getSerialState() & SERIAL_STATE_FLAG_CD) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDSR() throws IOException {
|
||||||
|
return (getSerialState() & SERIAL_STATE_FLAG_DSR) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getRI() throws IOException {
|
||||||
|
return (getSerialState() & SERIAL_STATE_FLAG_RI) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRTS(boolean value) throws IOException {
|
public void setRTS(boolean value) throws IOException {
|
||||||
mRts = value;
|
mRts = value;
|
||||||
@@ -333,15 +425,20 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EnumSet<ControlLine> getControlLines() throws IOException {
|
public EnumSet<ControlLine> getControlLines() throws IOException {
|
||||||
|
int serialState = getSerialState();
|
||||||
EnumSet<ControlLine> set = EnumSet.noneOf(ControlLine.class);
|
EnumSet<ControlLine> set = EnumSet.noneOf(ControlLine.class);
|
||||||
if(mRts) set.add(ControlLine.RTS);
|
if(mRts) set.add(ControlLine.RTS);
|
||||||
|
// no CTS
|
||||||
if(mDtr) set.add(ControlLine.DTR);
|
if(mDtr) set.add(ControlLine.DTR);
|
||||||
|
if((serialState & SERIAL_STATE_FLAG_DSR) != 0) set.add(ControlLine.DSR);
|
||||||
|
if((serialState & SERIAL_STATE_FLAG_CD) != 0) set.add(ControlLine.CD);
|
||||||
|
if((serialState & SERIAL_STATE_FLAG_RI) != 0) set.add(ControlLine.RI);
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EnumSet<ControlLine> getSupportedControlLines() throws IOException {
|
public EnumSet<ControlLine> getSupportedControlLines() throws IOException {
|
||||||
return EnumSet.of(ControlLine.RTS, ControlLine.DTR);
|
return EnumSet.of(ControlLine.RTS, ControlLine.DTR, ControlLine.DSR, ControlLine.CD, ControlLine.RI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+4
-8
@@ -260,10 +260,6 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean testStatusFlag(int flag) throws IOException {
|
|
||||||
return ((getStatus() & flag) == flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openInt() throws IOException {
|
public void openInt() throws IOException {
|
||||||
UsbInterface usbInterface = mDevice.getInterface(0);
|
UsbInterface usbInterface = mDevice.getInterface(0);
|
||||||
@@ -474,17 +470,17 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getCD() throws IOException {
|
public boolean getCD() throws IOException {
|
||||||
return testStatusFlag(STATUS_FLAG_CD);
|
return (getStatus() & STATUS_FLAG_CD) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getCTS() throws IOException {
|
public boolean getCTS() throws IOException {
|
||||||
return testStatusFlag(STATUS_FLAG_CTS);
|
return (getStatus() & STATUS_FLAG_CTS) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getDSR() throws IOException {
|
public boolean getDSR() throws IOException {
|
||||||
return testStatusFlag(STATUS_FLAG_DSR);
|
return (getStatus() & STATUS_FLAG_DSR) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -505,7 +501,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getRI() throws IOException {
|
public boolean getRI() throws IOException {
|
||||||
return testStatusFlag(STATUS_FLAG_RI);
|
return (getStatus() & STATUS_FLAG_RI) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user