added encoded baudrates in ftdi driver

pull/243/head
Felipe Herranz 2019-03-31 21:57:15 +02:00
rodzic 3e889f646f
commit ac88abca1a
1 zmienionych plików z 112 dodań i 1 usunięć

Wyświetl plik

@ -9,6 +9,7 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
import android.os.Build;
import android.util.Log;
import com.felhr.utils.SafeUsbRequest;
@ -92,7 +93,6 @@ public class FTDISerialDevice extends UsbSerialDevice
private UsbSerialInterface.UsbOverrunCallback overrunCallback;
private UsbSerialInterface.UsbBreakCallback breakCallback;
public FTDISerialDevice(UsbDevice device, UsbDeviceConnection connection)
{
this(device, connection, -1);
@ -707,4 +707,115 @@ public class FTDISerialDevice extends UsbSerialDevice
return read;
}
// https://stackoverflow.com/questions/47303802/how-is-androids-string-usbdevice-getversion-encoded-from-word-bcddevice
private short getBcdDevice() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
byte[] descriptors = connection.getRawDescriptors();
return (short) ((descriptors[12] << 8) + descriptors[13]);
}else{
return -1;
}
}
private byte getISerialNumber(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
byte[] descriptors = connection.getRawDescriptors();
return descriptors[16];
}else{
return -1;
}
}
private boolean isBaudTolerated(long speed, long target) {
return ((speed >= (target * 100) / 103) &&
(speed <= (target * 100) / 97));
}
// Encoding baudrate as freebsd driver:
// https://github.com/freebsd/freebsd/blob/1d6e4247415d264485ee94b59fdbc12e0c566fd0/sys/dev/usb/serial/uftdi.c
private short[] encodeBaudRate(int baudRate){
boolean isFT232A = false;
boolean clk12MHz = false;
boolean hIndex = false;
short[] ret = new short[2];
int clk, divisor, fastClk, frac, hwSpeed;
byte[] encodedFraction = new byte[]{
0, 3, 2, 4, 1, 5, 6, 7
};
byte[] roundoff232a = new byte[]{
0, 1, 0, 1, 0, -1, 2, 1,
0, -1, -2, -3, 4, 3, 2, 1,
};
short bcdDevice = getBcdDevice();
if(bcdDevice == -1) {
return null;
}
if(bcdDevice == 0x200 && getISerialNumber() == 0) {
isFT232A = true;
}
if(bcdDevice == 0x500 || bcdDevice == 0x700 || bcdDevice == 0x800 || bcdDevice == 0x900 || bcdDevice == 0x1000) {
hIndex = true;
}
if(bcdDevice == 0x700 || bcdDevice == 0x800 || bcdDevice == 0x900 ) {
clk12MHz = true;
}
if(baudRate >= 1200 && clk12MHz) {
clk = 12000000;
fastClk = (1 << 17);
}else {
clk = 3000000;
fastClk = 0;
}
if(baudRate < (clk >> 14) || baudRate > clk) {
return null;
}
divisor = (clk << 4) / baudRate;
if((divisor & 0xf) == 1) {
divisor &= 0xfffffff8;
}else if (isFT232A) {
divisor += roundoff232a[divisor & 0x0f];
}else {
divisor += 1; /* Rounds odd 16ths up to next 8th. */
}
divisor >>= 1;
hwSpeed = (clk << 3) / divisor;
if(!isBaudTolerated(hwSpeed, baudRate)) {
return null;
}
frac = divisor & 0x07;
divisor >>= 3;
if (divisor == 1) {
if (frac == 0) {
divisor = 0; /* 1.0 becomes 0.0 */
}else {
frac = 0; /* 1.5 becomes 1.0 */
}
}
divisor |= (encodedFraction[frac] << 14) | fastClk;
ret[0] = (short) divisor;
ret[1] = (short) (divisor >> 16);
if(hIndex) {
ret[1] <<= 8;
}
return ret;
}
}