1
0
mirror of https://github.com/mik3y/usb-serial-for-android synced 2025-06-08 00:16:13 +00:00

custom baud rates for PL2303TA/TB

see https://lore.kernel.org/r/3aee5708-7961-f464-8c5f-6685d96920d6@IEEE.org
This commit is contained in:
kai-morich 2021-05-10 23:21:31 +02:00
parent 22a685e738
commit 2f23bdfb6d
4 changed files with 58 additions and 34 deletions

View File

@ -26,6 +26,7 @@ import com.hoho.android.usbserial.driver.Cp21xxSerialDriver;
import com.hoho.android.usbserial.driver.FtdiSerialDriver; import com.hoho.android.usbserial.driver.FtdiSerialDriver;
import com.hoho.android.usbserial.driver.ProbeTable; import com.hoho.android.usbserial.driver.ProbeTable;
import com.hoho.android.usbserial.driver.ProlificSerialDriver; import com.hoho.android.usbserial.driver.ProlificSerialDriver;
import com.hoho.android.usbserial.driver.ProlificWrapper;
import com.hoho.android.usbserial.driver.SerialTimeoutException; import com.hoho.android.usbserial.driver.SerialTimeoutException;
import com.hoho.android.usbserial.driver.UsbId; import com.hoho.android.usbserial.driver.UsbId;
import com.hoho.android.usbserial.driver.UsbSerialDriver; import com.hoho.android.usbserial.driver.UsbSerialDriver;
@ -323,11 +324,12 @@ public class DeviceTest {
}; };
usb.open(); usb.open();
int minBaudRate = ProlificWrapper.isDeviceTypeT(usb.serialPort) ? 6 : 46;
try { try {
usb.setParameters(45, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(minBaudRate-1, 8, 1, UsbSerialPort.PARITY_NONE);
fail("baud rate to low expected"); fail("baud rate to low expected");
} catch(UnsupportedOperationException ignored) {} } catch(UnsupportedOperationException ignored) {}
usb.setParameters(46, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(minBaudRate, 8, 1, UsbSerialPort.PARITY_NONE);
usb.setParameters(384_000_000, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(384_000_000, 8, 1, UsbSerialPort.PARITY_NONE);
try { try {
usb.setParameters(384_000_001, 8, 1, UsbSerialPort.PARITY_NONE); usb.setParameters(384_000_001, 8, 1, UsbSerialPort.PARITY_NONE);

View File

@ -0,0 +1,8 @@
package com.hoho.android.usbserial.driver;
public class ProlificWrapper {
public static boolean isDeviceTypeT(UsbSerialPort serialPort) {
ProlificSerialDriver.ProlificSerialPort prolificSerialPort = (ProlificSerialDriver.ProlificSerialPort) serialPort;
return prolificSerialPort.mDeviceType == ProlificSerialDriver.DeviceType.DEVICE_TYPE_T;
}
}

View File

@ -21,7 +21,6 @@ import java.util.Deque;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;

View File

@ -35,7 +35,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
28800, 38400, 57600, 115200, 128000, 134400, 161280, 201600, 230400, 268800, 28800, 38400, 57600, 115200, 128000, 134400, 161280, 201600, 230400, 268800,
403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, 6000000 403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, 6000000
}; };
private enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_HX} protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX}
private final UsbDevice mDevice; private final UsbDevice mDevice;
private final UsbSerialPort mPort; private final UsbSerialPort mPort;
@ -98,7 +98,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
private static final int STATUS_BUFFER_SIZE = 10; private static final int STATUS_BUFFER_SIZE = 10;
private static final int STATUS_BYTE_IDX = 8; private static final int STATUS_BYTE_IDX = 8;
private DeviceType mDeviceType = DeviceType.DEVICE_TYPE_HX; protected DeviceType mDeviceType = DeviceType.DEVICE_TYPE_HX;
private UsbEndpoint mInterruptEndpoint; private UsbEndpoint mInterruptEndpoint;
private int mControlLinesValue = 0; private int mControlLinesValue = 0;
private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1; private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1;
@ -163,7 +163,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
vendorIn(0x8383, 0, 1); vendorIn(0x8383, 0, 1);
vendorOut(0, 1, null); vendorOut(0, 1, null);
vendorOut(1, 0, null); vendorOut(1, 0, null);
vendorOut(2, (mDeviceType == DeviceType.DEVICE_TYPE_HX) ? 0x44 : 0x24, null); vendorOut(2, (mDeviceType == DeviceType.DEVICE_TYPE_01) ? 0x24 : 0x44, null);
} }
private void setControlLines(int newControlLinesValue) throws IOException { private void setControlLines(int newControlLinesValue) throws IOException {
@ -253,26 +253,22 @@ public class ProlificSerialDriver implements UsbSerialDriver {
} }
} }
if (mDevice.getDeviceClass() == 0x02) {
mDeviceType = DeviceType.DEVICE_TYPE_01;
} else {
byte[] rawDescriptors = connection.getRawDescriptors(); byte[] rawDescriptors = connection.getRawDescriptors();
if(rawDescriptors == null || rawDescriptors.length <8) { if(rawDescriptors == null || rawDescriptors.length < 14) {
Log.w(TAG, "Could not get device descriptors, Assuming that it is a HX device"); throw new IOException("Could not get device descriptors");
mDeviceType = DeviceType.DEVICE_TYPE_HX; }
} else { int usbVersion = (rawDescriptors[3] << 8) + rawDescriptors[2];
int deviceVersion = (rawDescriptors[13] << 8) + rawDescriptors[12];
byte maxPacketSize0 = rawDescriptors[7]; byte maxPacketSize0 = rawDescriptors[7];
if (maxPacketSize0 == 64) { if (mDevice.getDeviceClass() == 0x02 || maxPacketSize0 != 64) {
mDeviceType = DeviceType.DEVICE_TYPE_HX;
} else if ((mDevice.getDeviceClass() == 0x00)
|| (mDevice.getDeviceClass() == 0xff)) {
mDeviceType = DeviceType.DEVICE_TYPE_01; mDeviceType = DeviceType.DEVICE_TYPE_01;
} else if(deviceVersion == 0x300 && usbVersion == 0x200) {
mDeviceType = DeviceType.DEVICE_TYPE_T; // TA
} else if(deviceVersion == 0x500) {
mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
} else { } else {
Log.w(TAG, "Could not detect PL2303 subtype, Assuming that it is a HX device");
mDeviceType = DeviceType.DEVICE_TYPE_HX; mDeviceType = DeviceType.DEVICE_TYPE_HX;
} }
}
}
setControlLines(mControlLinesValue); setControlLines(mControlLinesValue);
resetDevice(); resetDevice();
doBlackMagic(); doBlackMagic();
@ -315,21 +311,39 @@ public class ProlificSerialDriver implements UsbSerialDriver {
} }
/* /*
* Formula taken from Linux + FreeBSD. * Formula taken from Linux + FreeBSD.
*
* For TA+TB devices
* baudrate = baseline / (mantissa * 2^exponent)
* where
* mantissa = buf[10:0]
* exponent = buf[15:13 16]
*
* For other devices
* baudrate = baseline / (mantissa * 4^exponent) * baudrate = baseline / (mantissa * 4^exponent)
* where * where
* mantissa = buf[8:0] * mantissa = buf[8:0]
* exponent = buf[11:9] * exponent = buf[11:9]
* *
* Note: The formula does not work for all PL2303 variants.
* Ok for PL2303HX. Not ok for PL2303TA. Other variants unknown.
*/ */
int baseline, mantissa, exponent; int baseline, mantissa, exponent, buf, effectiveBaudRate;
baseline = 12000000 * 32; baseline = 12000000 * 32;
mantissa = baseline / baudRate; mantissa = baseline / baudRate;
if (mantissa == 0) { // > unrealistic 384 MBaud if (mantissa == 0) { // > unrealistic 384 MBaud
throw new UnsupportedOperationException("Baud rate to high"); throw new UnsupportedOperationException("Baud rate to high");
} }
exponent = 0; exponent = 0;
if (mDeviceType == DeviceType.DEVICE_TYPE_T) {
while (mantissa >= 2048) {
if (exponent < 15) {
mantissa >>= 1; /* divide by 2 */
exponent++;
} else { // < 7 baud
throw new UnsupportedOperationException("Baud rate to low");
}
}
buf = mantissa + ((exponent & ~1) << 12) + ((exponent & 1) << 16) + (1 << 31);
effectiveBaudRate = (baseline / mantissa) >> exponent;
} else {
while (mantissa >= 512) { while (mantissa >= 512) {
if (exponent < 7) { if (exponent < 7) {
mantissa >>= 2; /* divide by 4 */ mantissa >>= 2; /* divide by 4 */
@ -338,11 +352,12 @@ public class ProlificSerialDriver implements UsbSerialDriver {
throw new UnsupportedOperationException("Baud rate to low"); throw new UnsupportedOperationException("Baud rate to low");
} }
} }
int effectiveBaudRate = (baseline / mantissa) >> (exponent << 1); buf = mantissa + (exponent << 9) + (1 << 31);
effectiveBaudRate = (baseline / mantissa) >> (exponent << 1);
}
double baudRateError = Math.abs(1.0 - (effectiveBaudRate / (double)baudRate)); double baudRateError = Math.abs(1.0 - (effectiveBaudRate / (double)baudRate));
if(baudRateError >= 0.031) // > unrealistic 11.6 Mbaud if(baudRateError >= 0.031) // > unrealistic 11.6 Mbaud
throw new UnsupportedOperationException(String.format("Baud rate deviation %.1f%% is higher than allowed 3%%", baudRateError*100)); throw new UnsupportedOperationException(String.format("Baud rate deviation %.1f%% is higher than allowed 3%%", baudRateError*100));
int buf = mantissa + (exponent<<9) + (1<<31);
Log.d(TAG, String.format("baud rate=%d, effective=%d, error=%.1f%%, value=0x%08x, mantissa=%d, exponent=%d", Log.d(TAG, String.format("baud rate=%d, effective=%d, error=%.1f%%, value=0x%08x, mantissa=%d, exponent=%d",
baudRate, effectiveBaudRate, baudRateError*100, buf, mantissa, exponent)); baudRate, effectiveBaudRate, baudRateError*100, buf, mantissa, exponent));