public class CH340Chip { public boolean config(UsbDeviceConnection usbDeviceConnection) { if (!UartInit(usbDeviceConnection)) {//初始化串口 return false; } else {//配置串口 if (SetConfig(usbDeviceConnection, baudRate, (byte) 8, (byte) 1, (byte) 0, (byte) 0)) { Logger.i(TAG, "Uart Configed"); } else { return false; } } return true; } private boolean UartInit(UsbDeviceConnection usbDeviceConnection) { int ret; int size = 8; byte[] buffer = new byte[size]; Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_SERIAL_INIT, 0x0000, 0x0000); ret = Uart_Control_In(usbDeviceConnection, UartCmd.VENDOR_VERSION, 0x0000, 0x0000, buffer, 2); if (ret < 0) return false; Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_WRITE, 0x1312, 0xD982); Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_WRITE, 0x0f2c, 0x0004); ret = Uart_Control_In(usbDeviceConnection, UartCmd.VENDOR_READ, 0x2518, 0x0000, buffer, 2); if (ret < 0) return false; Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_WRITE, 0x2727, 0x0000); Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_MODEM_OUT, 0x00ff, 0x0000); return true; } private int Uart_Control_Out(UsbDeviceConnection usbDeviceConnection, int request, int value, int index) { int retval = 0; retval = usbDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR | UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_OUT, request, value, index, null, 0, timeOut); return retval; } private int Uart_Control_In(UsbDeviceConnection usbDeviceConnection, int request, int value, int index, byte[] buffer, int length) { int retval = 0; retval = usbDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR | UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_IN, request, value, index, buffer, length, timeOut); return retval; } private final class UartCmd { public static final int VENDOR_WRITE_TYPE = 0x40; public static final int VENDOR_READ_TYPE = 0xC0; public static final int VENDOR_READ = 0x95; public static final int VENDOR_WRITE = 0x9A; public static final int VENDOR_SERIAL_INIT = 0xA1; public static final int VENDOR_MODEM_OUT = 0xA4; public static final int VENDOR_VERSION = 0x5F; } private final class UsbType { public static final int USB_TYPE_VENDOR = (0x02 << 5); public static final int USB_RECIP_DEVICE = 0x00; public static final int USB_DIR_OUT = 0x00; /* to device */ public static final int USB_DIR_IN = 0x80; /* to host */ } private final class UartModem { public static final int TIOCM_LE = 0x001; public static final int TIOCM_DTR = 0x002; public static final int TIOCM_RTS = 0x004; public static final int TIOCM_ST = 0x008; public static final int TIOCM_SR = 0x010; public static final int TIOCM_CTS = 0x020; public static final int TIOCM_CAR = 0x040; public static final int TIOCM_RNG = 0x080; public static final int TIOCM_DSR = 0x100; public static final int TIOCM_CD = TIOCM_CAR; public static final int TIOCM_RI = TIOCM_RNG; public static final int TIOCM_OUT1 = 0x2000; public static final int TIOCM_OUT2 = 0x4000; public static final int TIOCM_LOOP = 0x8000; } private int Uart_Tiocmset(UsbDeviceConnection usbDeviceConnection, int set, int clear) { int control = 0; if ((set & UartModem.TIOCM_RTS) == UartModem.TIOCM_RTS) control |= UartIoBits.UART_BIT_RTS; if ((set & UartModem.TIOCM_DTR) == UartModem.TIOCM_DTR) control |= UartIoBits.UART_BIT_DTR; if ((clear & UartModem.TIOCM_RTS) == UartModem.TIOCM_RTS) control &= ~UartIoBits.UART_BIT_RTS; if ((clear & UartModem.TIOCM_DTR) == UartModem.TIOCM_DTR) control &= ~UartIoBits.UART_BIT_DTR; return Uart_Set_Handshake(usbDeviceConnection, control); } private int Uart_Set_Handshake(UsbDeviceConnection usbDeviceConnection, int control) { return Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_MODEM_OUT, ~control, 0); } private final class UartIoBits { public static final int UART_BIT_RTS = (1 << 6); public static final int UART_BIT_DTR = (1 << 5); } private boolean SetConfig(UsbDeviceConnection usbDeviceConnection, long baudRate, byte dataBit, byte stopBit, byte parity, byte flowControl) { int value = 0; int index = 0; char valueHigh = 0, valueLow = 0, indexHigh = 0, indexLow = 0; switch (parity) { case 0: /* NONE */ valueHigh = 0x00; break; case 1: /* ODD */ valueHigh |= 0x08; break; case 2: /* Even */ valueHigh |= 0x18; break; case 3: /* Mark */ valueHigh |= 0x28; break; case 4: /* Space */ valueHigh |= 0x38; break; default: /* None */ valueHigh = 0x00; break; } if (stopBit == 2) { valueHigh |= 0x04; } switch (dataBit) { case 5: valueHigh |= 0x00; break; case 6: valueHigh |= 0x01; break; case 7: valueHigh |= 0x02; break; case 8: valueHigh |= 0x03; break; default: valueHigh |= 0x03; break; } valueHigh |= 0xc0; valueLow = 0x9c; value |= valueLow; value |= (int) (valueHigh << 8); switch ((int) baudRate) { case 50: indexLow = 0; indexHigh = 0x16; break; case 75: indexLow = 0; indexHigh = 0x64; break; case 110: indexLow = 0; indexHigh = 0x96; break; case 135: indexLow = 0; indexHigh = 0xa9; break; case 150: indexLow = 0; indexHigh = 0xb2; break; case 300: indexLow = 0; indexHigh = 0xd9; break; case 600: indexLow = 1; indexHigh = 0x64; break; case 1200: indexLow = 1; indexHigh = 0xb2; break; case 1800: indexLow = 1; indexHigh = 0xcc; break; case 2400: indexLow = 1; indexHigh = 0xd9; break; case 4800: indexLow = 2; indexHigh = 0x64; break; case 19200: indexLow = 2; indexHigh = 0xd9; break; case 38400: indexLow = 3; indexHigh = 0x64; break; case 57600: indexLow = 3; indexHigh = 0x98; break; case 115200: indexLow = 3; indexHigh = 0xcc; break; case 230400: indexLow = 3; indexHigh = 0xe6; break; case 460800: indexLow = 3; indexHigh = 0xf3; break; case 500000: indexLow = 3; indexHigh = 0xf4; break; case 921600: indexLow = 7; indexHigh = 0xf3; break; case 1000000: indexLow = 3; indexHigh = 0xfa; break; case 2000000: indexLow = 3; indexHigh = 0xfd; break; case 3000000: indexLow = 3; indexHigh = 0xfe; break; default: // default baudRate "9600" indexLow = 2; indexHigh = 0xb2; break; } index |= 0x88 | indexLow; index |= (int) (indexHigh << 8); Uart_Control_Out(usbDeviceConnection, UartCmd.VENDOR_SERIAL_INIT, value, index); if (flowControl == 1) { Uart_Tiocmset(usbDeviceConnection, UartModem.TIOCM_DTR | UartModem.TIOCM_RTS, 0x00); } return true; } }