2013-05-21 22:15:36 +00:00
|
|
|
/* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
|
|
* USA.
|
|
|
|
*
|
2013-10-28 23:11:21 +00:00
|
|
|
* Project home page: https://github.com/mik3y/usb-serial-for-android
|
2013-05-21 22:15:36 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ported to usb-serial-for-android
|
|
|
|
* by Felix Hädicke <felixhaedicke@web.de>
|
|
|
|
*
|
|
|
|
* Based on the pyprolific driver written
|
|
|
|
* by Emmanuel Blot <emmanuel.blot@free.fr>
|
|
|
|
* See https://github.com/eblot/pyftdi
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.hoho.android.usbserial.driver;
|
|
|
|
|
|
|
|
import android.hardware.usb.UsbConstants;
|
|
|
|
import android.hardware.usb.UsbDevice;
|
|
|
|
import android.hardware.usb.UsbDeviceConnection;
|
|
|
|
import android.hardware.usb.UsbEndpoint;
|
|
|
|
import android.hardware.usb.UsbInterface;
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.lang.reflect.Method;
|
2013-10-28 23:11:21 +00:00
|
|
|
import java.util.Collections;
|
2020-06-28 18:10:45 +00:00
|
|
|
import java.util.EnumSet;
|
2013-05-21 22:15:36 +00:00
|
|
|
import java.util.LinkedHashMap;
|
2013-10-28 23:11:21 +00:00
|
|
|
import java.util.List;
|
2013-05-21 22:15:36 +00:00
|
|
|
import java.util.Map;
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
public class ProlificSerialDriver implements UsbSerialDriver {
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final String TAG = ProlificSerialDriver.class.getSimpleName();
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final UsbDevice mDevice;
|
|
|
|
private final UsbSerialPort mPort;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
public ProlificSerialDriver(UsbDevice device) {
|
|
|
|
mDevice = device;
|
2014-02-04 22:22:14 +00:00
|
|
|
mPort = new ProlificSerialPort(mDevice, 0);
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public List<UsbSerialPort> getPorts() {
|
|
|
|
return Collections.singletonList(mPort);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public UsbDevice getDevice() {
|
|
|
|
return mDevice;
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
class ProlificSerialPort extends CommonUsbSerialPort {
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int USB_READ_TIMEOUT_MILLIS = 1000;
|
|
|
|
private static final int USB_WRITE_TIMEOUT_MILLIS = 5000;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int USB_RECIP_INTERFACE = 0x01;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01;
|
|
|
|
private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
|
|
|
|
| UsbConstants.USB_TYPE_VENDOR;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN
|
|
|
|
| UsbConstants.USB_TYPE_VENDOR;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT
|
|
|
|
| UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int WRITE_ENDPOINT = 0x02;
|
|
|
|
private static final int READ_ENDPOINT = 0x83;
|
|
|
|
private static final int INTERRUPT_ENDPOINT = 0x81;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-10-24 20:25:36 +00:00
|
|
|
private static final int FLUSH_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int FLUSH_TX_REQUEST = 0x09;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int SET_LINE_REQUEST = 0x20;
|
|
|
|
private static final int SET_CONTROL_REQUEST = 0x22;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int CONTROL_DTR = 0x01;
|
|
|
|
private static final int CONTROL_RTS = 0x02;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int STATUS_FLAG_CD = 0x01;
|
|
|
|
private static final int STATUS_FLAG_DSR = 0x02;
|
|
|
|
private static final int STATUS_FLAG_RI = 0x08;
|
|
|
|
private static final int STATUS_FLAG_CTS = 0x80;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private static final int STATUS_BUFFER_SIZE = 10;
|
|
|
|
private static final int STATUS_BYTE_IDX = 8;
|
|
|
|
|
|
|
|
private static final int DEVICE_TYPE_HX = 0;
|
|
|
|
private static final int DEVICE_TYPE_0 = 1;
|
|
|
|
private static final int DEVICE_TYPE_1 = 2;
|
|
|
|
|
|
|
|
private int mDeviceType = DEVICE_TYPE_HX;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private UsbEndpoint mInterruptEndpoint;
|
|
|
|
|
|
|
|
private int mControlLinesValue = 0;
|
|
|
|
|
|
|
|
private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1;
|
|
|
|
|
|
|
|
private int mStatus = 0;
|
|
|
|
private volatile Thread mReadStatusThread = null;
|
|
|
|
private final Object mReadStatusThreadLock = new Object();
|
|
|
|
boolean mStopReadStatusThread = false;
|
|
|
|
private IOException mReadStatusException = null;
|
|
|
|
|
|
|
|
|
2014-02-04 22:22:14 +00:00
|
|
|
public ProlificSerialPort(UsbDevice device, int portNumber) {
|
|
|
|
super(device, portNumber);
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public UsbSerialDriver getDriver() {
|
|
|
|
return ProlificSerialDriver.this;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final byte[] inControlTransfer(int requestType, int request,
|
|
|
|
int value, int index, int length) throws IOException {
|
|
|
|
byte[] buffer = new byte[length];
|
|
|
|
int result = mConnection.controlTransfer(requestType, request, value,
|
|
|
|
index, buffer, length, USB_READ_TIMEOUT_MILLIS);
|
|
|
|
if (result != length) {
|
|
|
|
throw new IOException(
|
|
|
|
String.format("ControlTransfer with value 0x%x failed: %d",
|
|
|
|
value, result));
|
|
|
|
}
|
|
|
|
return buffer;
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final void outControlTransfer(int requestType, int request,
|
|
|
|
int value, int index, byte[] data) throws IOException {
|
|
|
|
int length = (data == null) ? 0 : data.length;
|
|
|
|
int result = mConnection.controlTransfer(requestType, request, value,
|
|
|
|
index, data, length, USB_WRITE_TIMEOUT_MILLIS);
|
|
|
|
if (result != length) {
|
|
|
|
throw new IOException(
|
|
|
|
String.format("ControlTransfer with value 0x%x failed: %d",
|
|
|
|
value, result));
|
|
|
|
}
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final byte[] vendorIn(int value, int index, int length)
|
|
|
|
throws IOException {
|
|
|
|
return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE,
|
|
|
|
PROLIFIC_VENDOR_READ_REQUEST, value, index, length);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final void vendorOut(int value, int index, byte[] data)
|
|
|
|
throws IOException {
|
|
|
|
outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE,
|
|
|
|
PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private void resetDevice() throws IOException {
|
|
|
|
purgeHwBuffers(true, true);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final void ctrlOut(int request, int value, int index, byte[] data)
|
|
|
|
throws IOException {
|
|
|
|
outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index,
|
|
|
|
data);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private void doBlackMagic() throws IOException {
|
|
|
|
vendorIn(0x8484, 0, 1);
|
|
|
|
vendorOut(0x0404, 0, null);
|
|
|
|
vendorIn(0x8484, 0, 1);
|
|
|
|
vendorIn(0x8383, 0, 1);
|
|
|
|
vendorIn(0x8484, 0, 1);
|
|
|
|
vendorOut(0x0404, 1, null);
|
|
|
|
vendorIn(0x8484, 0, 1);
|
|
|
|
vendorIn(0x8383, 0, 1);
|
|
|
|
vendorOut(0, 1, null);
|
|
|
|
vendorOut(1, 0, null);
|
|
|
|
vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setControlLines(int newControlLinesValue) throws IOException {
|
|
|
|
ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null);
|
|
|
|
mControlLinesValue = newControlLinesValue;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final void readStatusThreadFunction() {
|
|
|
|
try {
|
|
|
|
while (!mStopReadStatusThread) {
|
2013-05-21 22:15:36 +00:00
|
|
|
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
|
2013-10-28 23:11:21 +00:00
|
|
|
int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint,
|
2013-05-21 22:15:36 +00:00
|
|
|
buffer,
|
|
|
|
STATUS_BUFFER_SIZE,
|
2013-10-28 23:11:21 +00:00
|
|
|
500);
|
|
|
|
if (readBytesCount > 0) {
|
|
|
|
if (readBytesCount == STATUS_BUFFER_SIZE) {
|
|
|
|
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
|
|
|
|
} else {
|
|
|
|
throw new IOException(
|
|
|
|
String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d",
|
|
|
|
STATUS_BUFFER_SIZE,
|
|
|
|
readBytesCount));
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
mReadStatusException = e;
|
|
|
|
}
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final int getStatus() throws IOException {
|
|
|
|
if ((mReadStatusThread == null) && (mReadStatusException == null)) {
|
|
|
|
synchronized (mReadStatusThreadLock) {
|
|
|
|
if (mReadStatusThread == null) {
|
|
|
|
byte[] buffer = new byte[STATUS_BUFFER_SIZE];
|
|
|
|
int readBytes = mConnection.bulkTransfer(mInterruptEndpoint,
|
|
|
|
buffer,
|
|
|
|
STATUS_BUFFER_SIZE,
|
|
|
|
100);
|
|
|
|
if (readBytes != STATUS_BUFFER_SIZE) {
|
|
|
|
Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status");
|
|
|
|
} else {
|
|
|
|
mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2013-10-28 23:11:21 +00:00
|
|
|
|
|
|
|
mReadStatusThread = new Thread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
readStatusThreadFunction();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
mReadStatusThread.setDaemon(true);
|
|
|
|
mReadStatusThread.start();
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
/* throw and clear an exception which occured in the status read thread */
|
|
|
|
IOException readStatusException = mReadStatusException;
|
|
|
|
if (mReadStatusException != null) {
|
|
|
|
mReadStatusException = null;
|
|
|
|
throw readStatusException;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mStatus;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
private final boolean testStatusFlag(int flag) throws IOException {
|
|
|
|
return ((getStatus() & flag) == flag);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
2019-12-09 21:42:51 +00:00
|
|
|
public void openInt(UsbDeviceConnection connection) throws IOException {
|
2013-10-28 23:11:21 +00:00
|
|
|
UsbInterface usbInterface = mDevice.getInterface(0);
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
if (!connection.claimInterface(usbInterface, true)) {
|
|
|
|
throw new IOException("Error claiming Prolific interface 0");
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-12-09 21:42:51 +00:00
|
|
|
for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
|
|
|
|
UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i);
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-12-09 21:42:51 +00:00
|
|
|
switch (currentEndpoint.getAddress()) {
|
|
|
|
case READ_ENDPOINT:
|
|
|
|
mReadEndpoint = currentEndpoint;
|
|
|
|
break;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-12-09 21:42:51 +00:00
|
|
|
case WRITE_ENDPOINT:
|
|
|
|
mWriteEndpoint = currentEndpoint;
|
|
|
|
break;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-12-09 21:42:51 +00:00
|
|
|
case INTERRUPT_ENDPOINT:
|
|
|
|
mInterruptEndpoint = currentEndpoint;
|
|
|
|
break;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2019-12-09 21:42:51 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-12-09 21:42:51 +00:00
|
|
|
if (mDevice.getDeviceClass() == 0x02) {
|
|
|
|
mDeviceType = DEVICE_TYPE_0;
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
Method getRawDescriptorsMethod
|
|
|
|
= mConnection.getClass().getMethod("getRawDescriptors");
|
|
|
|
byte[] rawDescriptors
|
|
|
|
= (byte[]) getRawDescriptorsMethod.invoke(mConnection);
|
|
|
|
byte maxPacketSize0 = rawDescriptors[7];
|
|
|
|
if (maxPacketSize0 == 64) {
|
2013-05-21 22:15:36 +00:00
|
|
|
mDeviceType = DEVICE_TYPE_HX;
|
2019-12-09 21:42:51 +00:00
|
|
|
} else if ((mDevice.getDeviceClass() == 0x00)
|
|
|
|
|| (mDevice.getDeviceClass() == 0xff)) {
|
|
|
|
mDeviceType = DEVICE_TYPE_1;
|
|
|
|
} else {
|
|
|
|
Log.w(TAG, "Could not detect PL2303 subtype, "
|
|
|
|
+ "Assuming that it is a HX device");
|
|
|
|
mDeviceType = DEVICE_TYPE_HX;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2019-12-09 21:42:51 +00:00
|
|
|
} catch (NoSuchMethodException e) {
|
|
|
|
Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, "
|
|
|
|
+ "required for PL2303 subtype detection, not "
|
|
|
|
+ "available! Assuming that it is a HX device");
|
|
|
|
mDeviceType = DEVICE_TYPE_HX;
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(TAG, "An unexpected exception occured while trying "
|
|
|
|
+ "to detect PL2303 subtype", e);
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2019-12-09 21:42:51 +00:00
|
|
|
setControlLines(mControlLinesValue);
|
|
|
|
resetDevice();
|
|
|
|
doBlackMagic();
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
2019-11-09 21:48:00 +00:00
|
|
|
public void closeInt() {
|
2013-10-28 23:11:21 +00:00
|
|
|
try {
|
|
|
|
mStopReadStatusThread = true;
|
|
|
|
synchronized (mReadStatusThreadLock) {
|
|
|
|
if (mReadStatusThread != null) {
|
|
|
|
try {
|
|
|
|
mReadStatusThread.join();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.w(TAG, "An error occured while waiting for status read thread", e);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
}
|
2013-10-28 23:11:21 +00:00
|
|
|
resetDevice();
|
2019-11-09 21:48:00 +00:00
|
|
|
} catch(Exception ignored) {}
|
|
|
|
try {
|
|
|
|
mConnection.releaseInterface(mDevice.getInterface(0));
|
|
|
|
} catch(Exception ignored) {}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
2019-11-02 12:08:03 +00:00
|
|
|
public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException {
|
2013-10-28 23:11:21 +00:00
|
|
|
if ((mBaudRate == baudRate) && (mDataBits == dataBits)
|
|
|
|
&& (mStopBits == stopBits) && (mParity == parity)) {
|
|
|
|
// Make sure no action is performed if there is nothing to change
|
|
|
|
return;
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
byte[] lineRequestData = new byte[7];
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-11-02 12:08:03 +00:00
|
|
|
if(baudRate <= 0) {
|
|
|
|
throw new IllegalArgumentException("Invalid baud rate: " + baudRate);
|
|
|
|
}
|
2013-10-28 23:11:21 +00:00
|
|
|
lineRequestData[0] = (byte) (baudRate & 0xff);
|
|
|
|
lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff);
|
|
|
|
lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff);
|
|
|
|
lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff);
|
2013-11-07 00:02:05 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
switch (stopBits) {
|
|
|
|
case STOPBITS_1:
|
|
|
|
lineRequestData[4] = 0;
|
|
|
|
break;
|
|
|
|
case STOPBITS_1_5:
|
|
|
|
lineRequestData[4] = 1;
|
|
|
|
break;
|
|
|
|
case STOPBITS_2:
|
|
|
|
lineRequestData[4] = 2;
|
|
|
|
break;
|
|
|
|
default:
|
2019-11-02 12:08:03 +00:00
|
|
|
throw new IllegalArgumentException("Invalid stop bits: " + stopBits);
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
switch (parity) {
|
|
|
|
case PARITY_NONE:
|
|
|
|
lineRequestData[5] = 0;
|
|
|
|
break;
|
|
|
|
case PARITY_ODD:
|
|
|
|
lineRequestData[5] = 1;
|
|
|
|
break;
|
2015-03-13 11:50:14 +00:00
|
|
|
case PARITY_EVEN:
|
|
|
|
lineRequestData[5] = 2;
|
|
|
|
break;
|
2013-10-28 23:11:21 +00:00
|
|
|
case PARITY_MARK:
|
|
|
|
lineRequestData[5] = 3;
|
|
|
|
break;
|
|
|
|
case PARITY_SPACE:
|
|
|
|
lineRequestData[5] = 4;
|
|
|
|
break;
|
|
|
|
default:
|
2019-11-02 12:08:03 +00:00
|
|
|
throw new IllegalArgumentException("Invalid parity: " + parity);
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2019-11-02 12:08:03 +00:00
|
|
|
if(dataBits < DATABITS_5 || dataBits > DATABITS_8) {
|
|
|
|
throw new IllegalArgumentException("Invalid data bits: " + dataBits);
|
|
|
|
}
|
2013-10-28 23:11:21 +00:00
|
|
|
lineRequestData[6] = (byte) dataBits;
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
resetDevice();
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
mBaudRate = baudRate;
|
|
|
|
mDataBits = dataBits;
|
|
|
|
mStopBits = stopBits;
|
|
|
|
mParity = parity;
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getCD() throws IOException {
|
|
|
|
return testStatusFlag(STATUS_FLAG_CD);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getCTS() throws IOException {
|
|
|
|
return testStatusFlag(STATUS_FLAG_CTS);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getDSR() throws IOException {
|
|
|
|
return testStatusFlag(STATUS_FLAG_DSR);
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getDTR() throws IOException {
|
2020-06-28 18:10:45 +00:00
|
|
|
return (mControlLinesValue & CONTROL_DTR) != 0;
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public void setDTR(boolean value) throws IOException {
|
|
|
|
int newControlLinesValue;
|
|
|
|
if (value) {
|
|
|
|
newControlLinesValue = mControlLinesValue | CONTROL_DTR;
|
|
|
|
} else {
|
|
|
|
newControlLinesValue = mControlLinesValue & ~CONTROL_DTR;
|
|
|
|
}
|
|
|
|
setControlLines(newControlLinesValue);
|
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getRI() throws IOException {
|
|
|
|
return testStatusFlag(STATUS_FLAG_RI);
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public boolean getRTS() throws IOException {
|
2020-06-28 18:10:45 +00:00
|
|
|
return (mControlLinesValue & CONTROL_RTS) != 0;
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
|
|
|
public void setRTS(boolean value) throws IOException {
|
|
|
|
int newControlLinesValue;
|
|
|
|
if (value) {
|
|
|
|
newControlLinesValue = mControlLinesValue | CONTROL_RTS;
|
|
|
|
} else {
|
|
|
|
newControlLinesValue = mControlLinesValue & ~CONTROL_RTS;
|
|
|
|
}
|
|
|
|
setControlLines(newControlLinesValue);
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
2013-05-26 16:55:49 +00:00
|
|
|
|
2020-06-28 18:10:45 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public EnumSet<ControlLine> getControlLines() throws IOException {
|
|
|
|
int status = getStatus();
|
|
|
|
EnumSet<ControlLine> set = EnumSet.noneOf(ControlLine.class);
|
|
|
|
if((mControlLinesValue & CONTROL_RTS) != 0) set.add(ControlLine.RTS);
|
|
|
|
if((status & STATUS_FLAG_CTS) != 0) set.add(ControlLine.CTS);
|
|
|
|
if((mControlLinesValue & CONTROL_DTR) != 0) set.add(ControlLine.DTR);
|
|
|
|
if((status & STATUS_FLAG_DSR) != 0) set.add(ControlLine.DSR);
|
|
|
|
if((status & STATUS_FLAG_CD) != 0) set.add(ControlLine.CD);
|
|
|
|
if((status & STATUS_FLAG_RI) != 0) set.add(ControlLine.RI);
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public EnumSet<ControlLine> getSupportedControlLines() throws IOException {
|
|
|
|
return EnumSet.allOf(ControlLine.class);
|
|
|
|
}
|
|
|
|
|
2013-10-28 23:11:21 +00:00
|
|
|
@Override
|
2019-10-24 20:25:36 +00:00
|
|
|
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
|
|
|
if (purgeWriteBuffers) {
|
2013-10-28 23:11:21 +00:00
|
|
|
vendorOut(FLUSH_RX_REQUEST, 0, null);
|
|
|
|
}
|
|
|
|
|
2019-10-24 20:25:36 +00:00
|
|
|
if (purgeReadBuffers) {
|
2013-10-28 23:11:21 +00:00
|
|
|
vendorOut(FLUSH_TX_REQUEST, 0, null);
|
|
|
|
}
|
|
|
|
|
2019-10-24 20:25:36 +00:00
|
|
|
return true;
|
2013-10-28 23:11:21 +00:00
|
|
|
}
|
2013-05-21 22:15:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Map<Integer, int[]> getSupportedDevices() {
|
|
|
|
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
2019-10-24 20:25:36 +00:00
|
|
|
supportedDevices.put(UsbId.VENDOR_PROLIFIC,
|
2013-05-21 22:15:36 +00:00
|
|
|
new int[] { UsbId.PROLIFIC_PL2303, });
|
|
|
|
return supportedDevices;
|
|
|
|
}
|
|
|
|
}
|