mirror of
https://github.com/mik3y/usb-serial-for-android
synced 2025-06-07 16:06:10 +00:00
PL2303 fix initial input control line values
This commit is contained in:
parent
732e138630
commit
08a93ec530
@ -1573,14 +1573,6 @@ public class DeviceTest {
|
|||||||
Thread.sleep(sleep);
|
Thread.sleep(sleep);
|
||||||
|
|
||||||
assertEquals(supportedControlLines, usb.serialPort.getSupportedControlLines());
|
assertEquals(supportedControlLines, usb.serialPort.getSupportedControlLines());
|
||||||
if(usb.serialDriver instanceof ProlificSerialDriver) {
|
|
||||||
// the initial status is sometimes not available or wrong.
|
|
||||||
// this is more likely if other tests have been executed before.
|
|
||||||
// start thread and wait until status hopefully updated.
|
|
||||||
usb.serialPort.getRI(); // todo
|
|
||||||
Thread.sleep(sleep);
|
|
||||||
assertTrue(usb.serialPort.getRI());
|
|
||||||
}
|
|
||||||
|
|
||||||
// control lines reset on initial open
|
// control lines reset on initial open
|
||||||
data = "none".getBytes();
|
data = "none".getBytes();
|
||||||
@ -1680,27 +1672,59 @@ public class DeviceTest {
|
|||||||
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getCD), equalTo(inputLineFalse));
|
||||||
assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(inputLineFalse));
|
assertThat(usb.getControlLine(usb.serialPort::getRI), equalTo(inputLineFalse));
|
||||||
|
|
||||||
|
if (usb.serialDriver instanceof ProlificSerialDriver) { // check different control line mapping in GET_CONTROL_REQUEST
|
||||||
|
usb.serialPort.setRTS(false);
|
||||||
|
usb.serialPort.setDTR(false);
|
||||||
|
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
||||||
|
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
||||||
|
assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RI), usb.serialPort.getControlLines());
|
||||||
|
|
||||||
|
usb.serialPort.setRTS(true);
|
||||||
|
usb.serialPort.setDTR(false);
|
||||||
|
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
||||||
|
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
||||||
|
assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RTS, UsbSerialPort.ControlLine.CTS), usb.serialPort.getControlLines());
|
||||||
|
|
||||||
|
usb.serialPort.setRTS(false);
|
||||||
|
usb.serialPort.setDTR(true);
|
||||||
|
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
||||||
|
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
||||||
|
assertEquals(EnumSet.of(UsbSerialPort.ControlLine.DTR, UsbSerialPort.ControlLine.DSR), usb.serialPort.getControlLines());
|
||||||
|
|
||||||
|
usb.serialPort.setRTS(true);
|
||||||
|
usb.serialPort.setDTR(true);
|
||||||
|
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
||||||
|
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
||||||
|
assertEquals(EnumSet.of(UsbSerialPort.ControlLine.RTS, UsbSerialPort.ControlLine.DTR, UsbSerialPort.ControlLine.CD), usb.serialPort.getControlLines());
|
||||||
|
}
|
||||||
|
|
||||||
|
// force error
|
||||||
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
usb.close(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT));
|
||||||
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
usb.open(EnumSet.of(UsbWrapper.OpenCloseFlags.NO_CONTROL_LINE_INIT, UsbWrapper.OpenCloseFlags.NO_IOMANAGER_THREAD));
|
||||||
|
if (usb.serialDriver instanceof ProlificSerialDriver) {
|
||||||
|
usb.serialPort.getRI(); // start background thread
|
||||||
|
}
|
||||||
usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
|
usb.setParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE);
|
||||||
for (int i = 0; i < usb.serialDriver.getDevice().getInterfaceCount(); i++)
|
for (int i = 0; i < usb.serialDriver.getDevice().getInterfaceCount(); i++)
|
||||||
usb.deviceConnection.releaseInterface(usb.serialDriver.getDevice().getInterface(i));
|
usb.deviceConnection.releaseInterface(usb.serialDriver.getDevice().getInterface(i));
|
||||||
usb.deviceConnection.close();
|
usb.deviceConnection.close();
|
||||||
|
|
||||||
// set... error
|
|
||||||
try {
|
try {
|
||||||
usb.serialPort.setRTS(true);
|
usb.serialPort.setRTS(true);
|
||||||
fail("error expected");
|
fail("error expected");
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get... error
|
|
||||||
try {
|
try {
|
||||||
usb.serialPort.getRI();
|
if (usb.serialDriver instanceof ProlificSerialDriver) {
|
||||||
if (usb.serialDriver instanceof ProlificSerialDriver)
|
for(int i = 0; i < 10; i++) { // can take some time until background thread fails
|
||||||
; // todo: currently not possible to detect, as bulkTransfer in background thread does not distinguish timeout and error
|
usb.serialPort.getRI();
|
||||||
else
|
Thread.sleep(100);
|
||||||
fail("error expected");
|
}
|
||||||
|
} else {
|
||||||
|
usb.serialPort.getRI();
|
||||||
|
}
|
||||||
|
fail("error expected");
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
} catch (UnsupportedOperationException ignored) {
|
} catch (UnsupportedOperationException ignored) {
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ import android.util.Log;
|
|||||||
import com.hoho.android.usbserial.BuildConfig;
|
import com.hoho.android.usbserial.BuildConfig;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -76,12 +75,19 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library
|
private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library
|
||||||
private static final int FLUSH_TX_REQUEST = 0x09;
|
private static final int FLUSH_TX_REQUEST = 0x09;
|
||||||
|
|
||||||
private static final int SET_LINE_REQUEST = 0x20;
|
private static final int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING
|
||||||
private static final int SET_CONTROL_REQUEST = 0x22;
|
private static final int SET_CONTROL_REQUEST = 0x22; // same as CDC SET_CONTROL_LINE_STATE
|
||||||
|
private static final int GET_CONTROL_REQUEST = 0x87;
|
||||||
|
private static final int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length
|
||||||
|
|
||||||
private static final int CONTROL_DTR = 0x01;
|
private static final int CONTROL_DTR = 0x01;
|
||||||
private static final int CONTROL_RTS = 0x02;
|
private static final int CONTROL_RTS = 0x02;
|
||||||
|
|
||||||
|
private static final int GET_CONTROL_FLAG_CD = 0x02;
|
||||||
|
private static final int GET_CONTROL_FLAG_DSR = 0x04;
|
||||||
|
private static final int GET_CONTROL_FLAG_RI = 0x01;
|
||||||
|
private static final int GET_CONTROL_FLAG_CTS = 0x08;
|
||||||
|
|
||||||
private static final int STATUS_FLAG_CD = 0x01;
|
private static final int STATUS_FLAG_CD = 0x01;
|
||||||
private static final int STATUS_FLAG_DSR = 0x02;
|
private static final int STATUS_FLAG_DSR = 0x02;
|
||||||
private static final int STATUS_FLAG_RI = 0x08;
|
private static final int STATUS_FLAG_RI = 0x08;
|
||||||
@ -98,7 +104,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
private int mStatus = 0;
|
private int mStatus = 0;
|
||||||
private volatile Thread mReadStatusThread = null;
|
private volatile Thread mReadStatusThread = null;
|
||||||
private final Object mReadStatusThreadLock = new Object();
|
private final Object mReadStatusThreadLock = new Object();
|
||||||
boolean mStopReadStatusThread = false;
|
private boolean mStopReadStatusThread = false;
|
||||||
private IOException mReadStatusException = null;
|
private IOException mReadStatusException = null;
|
||||||
|
|
||||||
|
|
||||||
@ -111,51 +117,37 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
return ProlificSerialDriver.this;
|
return ProlificSerialDriver.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final byte[] inControlTransfer(int requestType, int request,
|
private byte[] inControlTransfer(int requestType, int request, int value, int index, int length) throws IOException {
|
||||||
int value, int index, int length) throws IOException {
|
|
||||||
byte[] buffer = new byte[length];
|
byte[] buffer = new byte[length];
|
||||||
int result = mConnection.controlTransfer(requestType, request, value,
|
int result = mConnection.controlTransfer(requestType, request, value, index, buffer, length, USB_READ_TIMEOUT_MILLIS);
|
||||||
index, buffer, length, USB_READ_TIMEOUT_MILLIS);
|
|
||||||
if (result != length) {
|
if (result != length) {
|
||||||
throw new IOException(
|
throw new IOException(String.format("ControlTransfer 0x%x failed: %d",value, result));
|
||||||
String.format("ControlTransfer with value 0x%x failed: %d",
|
|
||||||
value, result));
|
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void outControlTransfer(int requestType, int request,
|
private void outControlTransfer(int requestType, int request, int value, int index, byte[] data) throws IOException {
|
||||||
int value, int index, byte[] data) throws IOException {
|
|
||||||
int length = (data == null) ? 0 : data.length;
|
int length = (data == null) ? 0 : data.length;
|
||||||
int result = mConnection.controlTransfer(requestType, request, value,
|
int result = mConnection.controlTransfer(requestType, request, value, index, data, length, USB_WRITE_TIMEOUT_MILLIS);
|
||||||
index, data, length, USB_WRITE_TIMEOUT_MILLIS);
|
|
||||||
if (result != length) {
|
if (result != length) {
|
||||||
throw new IOException(
|
throw new IOException( String.format("ControlTransfer 0x%x failed: %d", value, result));
|
||||||
String.format("ControlTransfer with value 0x%x failed: %d",
|
|
||||||
value, result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final byte[] vendorIn(int value, int index, int length)
|
private byte[] vendorIn(int value, int index, int length) throws IOException {
|
||||||
throws IOException {
|
return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
|
||||||
return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
|
|
||||||
PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void vendorOut(int value, int index, byte[] data)
|
private void vendorOut(int value, int index, byte[] data) throws IOException {
|
||||||
throws IOException {
|
outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
|
||||||
outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
|
|
||||||
PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetDevice() throws IOException {
|
private void resetDevice() throws IOException {
|
||||||
purgeHwBuffers(true, true);
|
purgeHwBuffers(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void ctrlOut(int request, int value, int index, byte[] data)
|
private void ctrlOut(int request, int value, int index, byte[] data) throws IOException {
|
||||||
throws IOException {
|
outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, data);
|
||||||
outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
|
|
||||||
data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doBlackMagic() throws IOException {
|
private void doBlackMagic() throws IOException {
|
||||||
@ -177,7 +169,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
mControlLinesValue = newControlLinesValue;
|
mControlLinesValue = newControlLinesValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void readStatusThreadFunction() {
|
private void readStatusThreadFunction() {
|
||||||
try {
|
try {
|
||||||
while (!mStopReadStatusThread) {
|
while (!mStopReadStatusThread) {
|
||||||
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
|
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
|
||||||
@ -186,42 +178,33 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
if(readBytesCount == -1 && System.currentTimeMillis() < endTime)
|
if(readBytesCount == -1 && System.currentTimeMillis() < endTime)
|
||||||
testConnection();
|
testConnection();
|
||||||
if (readBytesCount > 0) {
|
if (readBytesCount > 0) {
|
||||||
if (readBytesCount == STATUS_BUFFER_SIZE) {
|
if (readBytesCount != STATUS_BUFFER_SIZE) {
|
||||||
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
|
throw new IOException("Invalid status notification, expected " + STATUS_BUFFER_SIZE + " bytes, got " + readBytesCount);
|
||||||
|
} else if(buffer[0] != (byte)STATUS_NOTIFICATION ) {
|
||||||
|
throw new IOException("Invalid status notification, expected " + STATUS_NOTIFICATION + " request, got " + buffer[0]);
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(
|
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
|
||||||
String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d",
|
|
||||||
STATUS_BUFFER_SIZE,
|
|
||||||
readBytesCount));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
mReadStatusException = e;
|
mReadStatusException = e;
|
||||||
}
|
}
|
||||||
|
//Log.d(TAG, "end control line status thread " + mStopReadStatusThread + " " + (mReadStatusException == null ? "-" : mReadStatusException.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int getStatus() throws IOException {
|
private int getStatus() throws IOException {
|
||||||
if ((mReadStatusThread == null) && (mReadStatusException == null)) {
|
if ((mReadStatusThread == null) && (mReadStatusException == null)) {
|
||||||
synchronized (mReadStatusThreadLock) {
|
synchronized (mReadStatusThreadLock) {
|
||||||
if (mReadStatusThread == null) {
|
if (mReadStatusThread == null) {
|
||||||
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
|
byte[] data = vendorIn(GET_CONTROL_REQUEST, 0, 1);
|
||||||
int readBytes = mConnection.bulkTransfer(mInterruptEndpoint,
|
mStatus = 0;
|
||||||
buffer,
|
if((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
|
||||||
STATUS_BUFFER_SIZE,
|
if((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
|
||||||
100);
|
if((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
|
||||||
if (readBytes != STATUS_BUFFER_SIZE) {
|
if((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
|
||||||
Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status");
|
//Log.d(TAG, "start control line status thread " + mStatus);
|
||||||
} else {
|
mReadStatusThread = new Thread(this::readStatusThreadFunction);
|
||||||
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
mReadStatusThread = new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
readStatusThreadFunction();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mReadStatusThread.setDaemon(true);
|
mReadStatusThread.setDaemon(true);
|
||||||
mReadStatusThread.start();
|
mReadStatusThread.start();
|
||||||
}
|
}
|
||||||
@ -238,7 +221,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean testStatusFlag(int flag) throws IOException {
|
private boolean testStatusFlag(int flag) throws IOException {
|
||||||
return ((getStatus() & flag) == flag);
|
return ((getStatus() & flag) == flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,14 +279,17 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||||||
@Override
|
@Override
|
||||||
public void closeInt() {
|
public void closeInt() {
|
||||||
try {
|
try {
|
||||||
mStopReadStatusThread = true;
|
|
||||||
synchronized (mReadStatusThreadLock) {
|
synchronized (mReadStatusThreadLock) {
|
||||||
if (mReadStatusThread != null) {
|
if (mReadStatusThread != null) {
|
||||||
try {
|
try {
|
||||||
|
mStopReadStatusThread = true;
|
||||||
mReadStatusThread.join();
|
mReadStatusThread.join();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "An error occured while waiting for status read thread", e);
|
Log.w(TAG, "An error occured while waiting for status read thread", e);
|
||||||
}
|
}
|
||||||
|
mStopReadStatusThread = false;
|
||||||
|
mReadStatusThread = null;
|
||||||
|
mReadStatusException = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resetDevice();
|
resetDevice();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user