【背景】
新买的USB的HART猫:
【记录】为USB接口的HART猫ExSaf ESH232U安装对应的USB转RS232驱动
【记录】使用USB口的HART猫ExSaf ESH232U去检测某HART设备
其内部是Silicon Labs的CP2102的USB转串口的芯片。
现在是,希望将其用到之前:
已经支持了FTDI的FT232R的usb-serial-for-android
中的CP2102,也去添加对应的RTS和DTR,使得也可以用此HART猫去和HART设备通讯。
【折腾过程】
1.之前整理的一些可参考的资料:
2.
http://124.16.139.131:24080/lxr/source/kernel/omap/drivers/usb/serial/cp210x.c?v=android-4.0.4
中有:
#define REQTYPE_HOST_TO_DEVICE 0x41
和
3.
http://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx
中的源码:
4.
http://code.google.com/p/usb-serial-for-android/issues/detail?id=17
或许也有参考价值。
然后发现了,对于下载到的:
http://www.firmsys.com/down/UARTtoUSB.zip
其中包含了之前就知道的:
CP2102的
Linux_3.x.x_VCP_Driver_Source.zip
其中的驱动,就是我后来看到的:
http://lxr.free-electrons.com/source/drivers/usb/serial/cp210x.c#L286
5.参考源码后,就去折腾:
D:\DevRoot\android\android_root\UsbSerialLibrary\src\com\hoho\android\usbserial\driver\Cp2102SerialDriver.java |
中的内容,尤其是:
@Override public void setRTS(boolean value) throws IOException { } @Override public void setDTR(boolean value) throws IOException { }
6.开始折腾了,去:
http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx
供参考。
7.开始是参考:
D:\DevTool\USB-To-RS232\Linux_2.6.x_VCP_Driver_Source\Linux_2.6.x_VCP_Driver_Source\cp210x.c |
去写代码的。
8.但是期间发现,很多细节的定义,还是需要找对应的datasheet看,才更清楚。
所以去搜CP2102的datasheet,但是搜到:
https://www.sparkfun.com/datasheets/IC/cp2102.pdf
http://www.sinforcon.com/down/html/50.html
https://www.sparkfun.com/datasheets/PCB/CP2102%20Breakout-v01.pdf
却没有找到想要包含RTS DTR的位含义的定义的寄存器。。
9.另外,关于:
TIOCM_DTR
和
TIOCM_RTS
代码中找不到,也没有对应的.h头文件。
10.后来是在:
http://lxr.free-electrons.com/source/drivers/usb/serial/cp210x.c#L286
->
http://lxr.free-electrons.com/ident?i=TIOCM_DTR
->
http://lxr.free-electrons.com/source/include/uapi/asm-generic/termios.h#L33
找到的:
/* modem lines */ #define TIOCM_DTR 0x002 #define TIOCM_RTS 0x004 #define TIOCM_CTS 0x020 #define TIOCM_DSR 0x100
11.但是折腾代码期间,发现其原先有个问题:
setParameters
中,先去对于configDataBits,configParityBits,configStopBits
竟然是分别三次都单独设置一次,去调用setConfigSingle
而对应的
D:\DevTool\USB-To-RS232\Linux_2.6.x_VCP_Driver_Source\Linux_2.6.x_VCP_Driver_Source\cp210x.c
是:
分别计算对应的值,得到合并后的配置的值,然后最后只去调用一次:
cp210x_set_config
不过,后来又在:
D:\DevTool\USB-To-RS232\Silicon Labs\CP210x\UARTtoUSB\Ver.3.0\Driver\Linux_3.x.x_VCP_Driver_Source\Linux_3.x.x_VCP_Driver_Source\cp210x.c
中看到:
也是分别对于三种配置,分别去配置的。
但是很明显:
其三次调用
cp210x_set_config
去配置对应的值bits,都是分别获得最新的bits值,然后加上当前的配置,才去写入的。
而上面的代码中:
configDataBits,configParityBits,configStopBits
三个值,都只是自己独立的值:
搞得配置后面一个配置,就把之前的配置冲掉了。。。
所以,去改对应的代码为:
@Override public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException { setBaudRate(baudRate); int configBits = 0; //int configDataBits = 0; switch (dataBits) { case DATABITS_5: configBits |= 0x0500; break; case DATABITS_6: configBits |= 0x0600; break; case DATABITS_7: configBits |= 0x0700; break; case DATABITS_8: configBits |= 0x0800; break; default: configBits |= 0x0800; break; } //setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits); //int configParityBits = 0; // PARITY_NONE switch (parity) { case PARITY_ODD: configBits |= 0x0010; break; case PARITY_EVEN: configBits |= 0x0020; break; } //setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configParityBits); //int configStopBits = 0; switch (stopBits) { case STOPBITS_1: configBits |= 0; break; case STOPBITS_1_5: configBits |= 1; break; case STOPBITS_2: configBits |= 2; break; } //setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configStopBits); setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configBits); }
12.后面继续去调试。
然后发现:
http://code.google.com/p/usb-serial-for-android/issues/detail?id=17
中的patch:
才是,根据cp210x.c修正后的,更加完整的驱动。
然后想办法去打上此patch:
还是参考之前的:
结果是:
CLi@PC-CLI-1 /cygdrive/d/DevTool/Android/libs/usb serial/usb-serial-for-android $ ls -lha total 61K drwx------+ 1 Administrators Domänen-Benutzer 0 Nov 27 12:48 ./ drwx------+ 1 Administrators Domänen-Benutzer 0 Nov 27 12:48 ../ -rwx------+ 1 Administrators Domänen-Benutzer 218 Nov 7 10:34 .gitignore* drwx------+ 1 Administrators Domänen-Benutzer 0 Nov 27 12:46 arduino/ -rwx------+ 1 Administrators Domänen-Benutzer 673 Nov 7 10:34 CHANGELOG.txt* -rwx------+ 1 Administrators Domänen-Benutzer 7.5K Nov 7 10:34 LICENSE.txt* -rwx------+ 1 Administrators Domänen-Benutzer 4.0K Nov 7 10:34 README.md* drwx------+ 1 Administrators Domänen-Benutzer 0 Nov 27 12:46 UsbSerialExamples/ -rwx------+ 1 Administrators Domänen-Benutzer 27K Nov 27 12:45 usb-serial-for-android-cp210x.patch* drwx------+ 1 Administrators Domänen-Benutzer 0 Nov 27 12:46 UsbSerialLibrary/ CLi@PC-CLI-1 /cygdrive/d/DevTool/Android/libs/usb serial/usb-serial-for-android $ patch -p1 < usb-serial-for-android-cp210x.patch patching file UsbSerialExamples/project.properties patching file UsbSerialExamples/res/xml/device_filter.xml Hunk #1 succeeded at 11 with fuzz 2 (offset 3 lines). patching file UsbSerialLibrary/project.properties patching file UsbSerialLibrary/src/com/hoho/android/usbserial/driver/CP210xSerialDriver.java patching file UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java Hunk #1 FAILED at 51. 1 out of 1 hunk FAILED -- saving rejects to file UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbId.java.rej patching file UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialDriver.java Hunk #1 succeeded at 79 with fuzz 2 (offset 9 lines). patching file UsbSerialLibrary/src/com/hoho/android/usbserial/driver/UsbSerialProber.java Hunk #1 succeeded at 112 with fuzz 2 (offset 45 lines). patching file UsbSerialLibrary/src/com/hoho/android/usbserial/util/SerialInputOutputManager.java
很明显,部分内容没有完全打上。
估计是版本不匹配?
另外看到:
https://github.com/mik3y/usb-serial-for-android/issues/17
中说已经在2b3528b 合并了此补丁了。
所以,那就去:
https://github.com/mik3y/usb-serial-for-android
下载最新的代码,看看是否的确已经合并。
结果貌似最新的代码,和我之前就已经下载的,是一样的。
即:
最新的代码中,虽然像:
说的:
“A similar patch was merged in 2b3528b”
但是实际上,从master下载到最新的:
usb-serial-for-android-master.zip
中,对应的
CP210xSerialDriver.java
中的代码,却不是上面patch中的。
因为该patch中是:
CP210xSerialDriver.java
且包含对应的定义,都是和之前的Linux中的cp210x.c中都是一致的;
而新下载到的usb-serial-for-android-master.zip,中是:
Cp2102SerialDriver.java
且其中很多代码,就是我前面提到的,写法都是不正确的。
算了,单独从patch中,拷贝出对应的:
CP210xSerialDriver.java
然后保存后,和当前已有的
Cp2102SerialDriver.java
去比较看看。
算了,最后决定,还是手动去合并这个patch,使得不仅仅支持CP2102,而是支持CP210x。
13.后来写了代码:
/* Copyright 2011 Google Inc. * * 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. * * Project home page: http://code.google.com/p/usb-serial-for-android/ */ 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.hardware.usb.UsbRequest; import android.util.Log; import java.io.IOException; import java.nio.ByteBuffer; import java.util.LinkedHashMap; import java.util.Map; /** * A {@link UsbSerialDriver} implementation for a variety of CP210x devices * <p> * This driver is based on the source codes from linux kernel 3.7. * * </p> * <p> * Not all devices are tested. * <ul> * <li>Read and write of serial data (see {@link #read(byte[], int)} and * {@link #write(byte[], int)}. * <li>Setting baud rate (see {@link #setBaudRate(int)}). * </ul> * </p> * * * @author Jongmoo Sohn (jmthegrey@gmail.com) * @see <a href="http://code.google.com/p/usb-serial-for-android/">USB Serial * for Android project page</a> */ public class Cp210xSerialDriver extends CommonUsbSerialDriver { private final String TAG = Cp210xSerialDriver.class.getSimpleName(); /* Config request types */ private static final int REQTYPE_HOST_TO_INTERFACE = 0x41; private static final int REQTYPE_INTERFACE_TO_HOST = 0xc1; private static final int REQTYPE_HOST_TO_DEVICE = 0x40; private static final int REQTYPE_DEVICE_TO_HOST = 0xc0; /* Config request codes */ private static final int CP210X_IFC_ENABLE = 0x00; private static final int CP210X_SET_BAUDDIV = 0x01; private static final int CP210X_GET_BAUDDIV = 0x02; private static final int CP210X_SET_LINE_CTL = 0x03; private static final int CP210X_GET_LINE_CTL = 0x04; private static final int CP210X_SET_BREAK = 0x05; private static final int CP210X_IMM_CHAR = 0x06; private static final int CP210X_SET_MHS = 0x07; private static final int CP210X_GET_MDMSTS = 0x08; private static final int CP210X_SET_XON = 0x09; private static final int CP210X_SET_XOFF = 0x0A; private static final int CP210X_SET_EVENTMASK = 0x0B; private static final int CP210X_GET_EVENTMASK = 0x0C; private static final int CP210X_SET_CHAR = 0x0D; private static final int CP210X_GET_CHARS = 0x0E; private static final int CP210X_GET_PROPS = 0x0F; private static final int CP210X_GET_COMM_STATUS = 0x10; private static final int CP210X_RESET = 0x11; private static final int CP210X_PURGE = 0x12; private static final int CP210X_SET_FLOW = 0x13; private static final int CP210X_GET_FLOW = 0x14; private static final int CP210X_EMBED_EVENTS = 0x15; private static final int CP210X_GET_EVENTSTATE = 0x16; private static final int CP210X_SET_CHARS = 0x19; private static final int CP210X_GET_BAUDRATE = 0x1D; private static final int CP210X_SET_BAUDRATE = 0x1E; /* CP210X_IFC_ENABLE */ private static final int UART_ENABLE = 0x0001; private static final int UART_DISABLE = 0x0000; /* CP210X_(SET|GET)_BAUDDIV */ private static final int BAUD_RATE_GEN_FREQ = 0x384000; /* CP210X_(SET|GET)_LINE_CTL */ private static final int BITS_DATA_MASK = 0X0f00; private static final int BITS_DATA_5 = 0X0500; private static final int BITS_DATA_6 = 0X0600; private static final int BITS_DATA_7 = 0X0700; private static final int BITS_DATA_8 = 0X0800; private static final int BITS_DATA_9 = 0X0900; private static final int BITS_PARITY_MASK = 0x00f0; private static final int BITS_PARITY_NONE = 0x0000; private static final int BITS_PARITY_ODD = 0x0010; private static final int BITS_PARITY_EVEN = 0x0020; private static final int BITS_PARITY_MARK = 0x0030; private static final int BITS_PARITY_SPACE = 0x0040; private static final int BITS_STOP_MASK = 0x000f; private static final int BITS_STOP_1 = 0x0000; private static final int BITS_STOP_1_5 = 0x0001; private static final int BITS_STOP_2 = 0x0002; /* CP210X_SET_BREAK */ private static final int BREAK_ON = 0x0001; private static final int BREAK_OFF = 0x0000; /* CP210X_(SET_MHS|GET_MDMSTS) */ private static final int CONTROL_DTR = 0x0001; private static final int CONTROL_RTS = 0x0002; private static final int CONTROL_CTS = 0x0010; private static final int CONTROL_DSR = 0x0020; private static final int CONTROL_RING = 0x0040; private static final int CONTROL_DCD = 0x0080; private static final int CONTROL_WRITE_DTR = 0x0100; private static final int CONTROL_WRITE_RTS = 0x0200; private int mBulkInSize = 256; private int mBaudRate = 0; private int mDataBits = 0; private int mParity = 0; private int mStopBits = 0; private static final int DEFAULT_BAUD_RATE = 115200; private static final int DEFAULT_DATA_BITS = DATABITS_8; private static final int DEFAULT_PARITY = PARITY_NONE; private static final int DEFAULT_STOP_BITS = STOPBITS_1; /** * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads * since it gives no indication of number of bytes read. Set this to * {@code true} on platforms where it is fixed. * Safe to assume anything less than API level 17 is broken. */ private static final boolean ENABLE_ASYNC_READS = true; private UsbEndpoint mEndpointOut = null; private UsbEndpoint mEndpointIn = null; public static final int USB_CTRL_GET_TIMEOUT_MILLIS = 5000; public static final int USB_CTRL_SET_TIMEOUT_MILLIS = 5000; private boolean mRts = false; private boolean mDtr = false; /** * Constructor. * * @param usbDevice the {@link UsbDevice} to use * @param usbConnection the {@link UsbDeviceConnection} to use * @throws UsbSerialRuntimeException if the given device is incompatible * with this driver */ public Cp210xSerialDriver(UsbDevice usbDevice, UsbDeviceConnection usbConnection) { super(usbDevice, usbConnection); UsbInterface intf = findInterface(usbDevice); if (setInterface(usbDevice, intf)) { UsbEndpoint epOut = null; UsbEndpoint epIn = null; // Look for bulk endpoints for (int i = 0; i < intf.getEndpointCount(); i++) { UsbEndpoint ep = intf.getEndpoint(i); if (UsbConstants.USB_ENDPOINT_XFER_BULK == ep.getType()) { if (UsbConstants.USB_DIR_OUT == ep.getDirection()) { epOut = ep; Log.d(TAG, "endpointOut: " + i); } else { epIn = ep; Log.d(TAG, "endpointIn: " + i); } } } if (epOut == null || epIn == null) { throw new IllegalArgumentException("Not all endpoints found"); } mEndpointOut = epOut; mEndpointIn = epIn; } } private UsbInterface findInterface(UsbDevice device) { Log.d(TAG, "findInterface " + device); int count = device.getInterfaceCount(); for (int i =0 ; i < count ; i++) { UsbInterface intf = device.getInterface(i); Log.d(TAG, "Interface: " + count + " Class: " + intf.getInterfaceClass() + " Subclass: " + intf.getInterfaceSubclass() + " Protocol: " + intf.getInterfaceProtocol()); if (intf.getInterfaceClass() == 255 && intf.getInterfaceSubclass() == 00 && intf.getInterfaceProtocol() == 0) { return intf; } } return null; } private boolean setInterface(UsbDevice device, UsbInterface intf) { if (mConnection != null) { Log.d(TAG, "Open succeeded."); if (mConnection.claimInterface(intf, false)) { Log.d(TAG, "Claim interface succeeded."); return true; } else { Log.d(TAG, "Claim interface failed."); } } else { Log.d(TAG, "No connection to set interface."); } return false; } private int cp210x_set_config(int request, int value, byte[] buffer, int length) throws IOException { int result = mConnection.controlTransfer(REQTYPE_HOST_TO_INTERFACE, request, value, 0x0 /* index */, buffer, length, USB_CTRL_SET_TIMEOUT_MILLIS); if (result != length) { throw new IOException("cp210x_set_config failed: result=" + result); } return result; } private int cp210x_set_config_single(int request, int value) throws IOException { return cp210x_set_config(request, value, null, 0x0); } // From Sniffed Data private static final byte[] CP210X_SET_CHARS_DATA = { (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00 }; // From Sniffed Data private static final byte[] CP210X_SET_FLOW_DATA = { (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }; @Override public void open() throws IOException { boolean opened = false; try { for (int i = 0; i < mDevice.getInterfaceCount(); i++) { if (mConnection.claimInterface(mDevice.getInterface(i), true)) { Log.d(TAG, "claimInterface " + i + " SUCCESS"); } else { Log.d(TAG, "claimInterface " + i + " FAIL"); } } // Configure Single Port // cp210x_set_config_single(CP210X_IFC_ENABLE, UART_ENABLE); // From Sniffed Data cp210x_set_config_single(CP210X_IFC_ENABLE, 0xFFFF); // UART_ENABLE = 0x0001? 0xFFFF? cp210x_set_config(CP210X_SET_CHARS, 0x0000, CP210X_SET_CHARS_DATA, CP210X_SET_CHARS_DATA.length); cp210x_set_config(CP210X_SET_FLOW, 0x0000, CP210X_SET_FLOW_DATA, CP210X_SET_FLOW_DATA.length); // Configure the termios structure // cp210x_get_termios() NOT IMPLEMENTED ! // Instead, following default values are set. if (0 == mBaudRate) mBaudRate = DEFAULT_BAUD_RATE; if (0 == mDataBits) mDataBits = DEFAULT_DATA_BITS; if (0 == mParity) mParity = DEFAULT_PARITY; if (0 == mStopBits) mStopBits = DEFAULT_STOP_BITS; // The baud rate must be initialised on cp2104 // cp210x_change_speed(mBaudRate); setParameters(mBaudRate, mDataBits, mStopBits, mParity); // From Sniffed Data cp210x_set_config_single(CP210X_SET_MHS, CONTROL_WRITE_RTS); // 0x0200 cp210x_set_config_single(CP210X_SET_MHS, CONTROL_WRITE_DTR + CONTROL_DTR); // 0x0101 cp210x_set_config_single(CP210X_SET_BREAK, BREAK_OFF); opened = true; } finally { if (!opened) { close(); } } } @Override public void close() { try { // From Sniffed Data cp210x_set_config_single(CP210X_SET_BREAK, BREAK_OFF); cp210x_set_config_single(CP210X_IFC_ENABLE, UART_DISABLE); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mConnection.close(); } @Override public int read(byte[] dest, int timeoutMillis) throws IOException { if (ENABLE_ASYNC_READS) { final int readAmt; synchronized (mReadBufferLock) { // mReadBuffer is only used for maximum read size. readAmt = Math.min(dest.length, mReadBuffer.length); } final UsbRequest request = new UsbRequest(); request.initialize(mConnection, mEndpointIn); final ByteBuffer buf = ByteBuffer.wrap(dest); if (!request.queue(buf, readAmt)) { throw new IOException("Error queueing request."); } final UsbRequest response = mConnection.requestWait(); if (response == null) { throw new IOException("Null response"); } final int BytesRead = buf.position(); if (BytesRead > 0) { // Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length))); return BytesRead; } else { return 0; } } else { final int totalBytesRead; synchronized (mReadBufferLock) { final int readAmt = Math.min(dest.length, mReadBuffer.length); totalBytesRead = mConnection.bulkTransfer(mEndpointIn, mReadBuffer, readAmt, timeoutMillis); } if (totalBytesRead > 0) { System.arraycopy(mReadBuffer, 0, dest, 0, totalBytesRead); } return totalBytesRead; } } @Override public int write(byte[] src, int timeoutMillis) throws IOException { int offset = 0; while (offset < src.length) { final int writeLength; final int amtWritten; synchronized (mWriteBufferLock) { final byte[] writeBuffer; writeLength = Math.min(src.length - offset, mWriteBuffer.length); if (offset == 0) { writeBuffer = src; } else { // bulkTransfer does not support offsets, make a copy. System.arraycopy(src, offset, mWriteBuffer, 0, writeLength); writeBuffer = mWriteBuffer; } amtWritten = mConnection.bulkTransfer(mEndpointOut, writeBuffer, writeLength, timeoutMillis); } if (amtWritten <= 0) { throw new IOException("Error writing " + writeLength + " bytes at offset " + offset + " length=" + src.length); } Log.d(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength); offset += amtWritten; } return offset; } @Override @Deprecated public int setBaudRate(int baudRate) throws IOException { mBaudRate = cp210x_quantise_baudrate(baudRate); cp210x_change_speed(mBaudRate); return mBaudRate; } @Override public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException { mBaudRate = cp210x_quantise_baudrate(baudRate); cp210x_change_speed(mBaudRate); int config = 0x0000; switch (dataBits) { case DATABITS_5: config |= BITS_DATA_5; break; case DATABITS_6: config |= BITS_DATA_6; break; case DATABITS_7: config |= BITS_DATA_7; break; case DATABITS_8: config |= BITS_DATA_8; break; default: throw new IllegalArgumentException("Unknown dataBits value: " + dataBits); } switch (parity) { case PARITY_NONE: config |= BITS_PARITY_NONE; break; case PARITY_ODD: config |= BITS_PARITY_ODD; break; case PARITY_EVEN: config |= BITS_PARITY_EVEN; break; case PARITY_MARK: config |= BITS_PARITY_MARK; break; case PARITY_SPACE: config |= BITS_PARITY_SPACE; break; default: throw new IllegalArgumentException("Unknown parity value: " + parity); } switch (stopBits) { case STOPBITS_1: config |= BITS_STOP_1; break; case STOPBITS_1_5: config |= BITS_STOP_1_5; break; case STOPBITS_2: config |= BITS_STOP_2; break; default: throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); } int result = mConnection.controlTransfer(REQTYPE_HOST_TO_INTERFACE, CP210X_SET_LINE_CTL, config, 0 /* index */, null, 0, USB_CTRL_SET_TIMEOUT_MILLIS); if (result != 0) { throw new IOException("Setting parameters failed: result=" + result); } mParity = parity; mStopBits = stopBits; mDataBits = dataBits; verifyConfig(baudRate, config); } //convert byte array to integer type value //possible returned value: byte/short/int/long //Note: max support long -> input byte array length should not exceed 8 public static long byteArrToInteger(byte[] byteArr){ long convertedInterger = 0; //follow works: //int readbackBaudrate= (baudrateByteArr[3]<<24)&0xff000000|(baudrateByteArr[2]<<16)&0xff0000|(baudrateByteArr[1]<<8)&0xff00|(baudrateByteArr[0]<<0)&0xff; //115200 == [0, -62, 1, 0] //1200==[-80, 4, 0, 0] for(int i = 0; i < byteArr.length; i++){ //long curValue = byteArr[i]; //int curValue = byteArr[i]; byte curValue = byteArr[i]; long shiftedValue = curValue << (i * 8); long mask = 0xFF << (i * 8); long maskedShiftedValue = shiftedValue & mask; //0x0, 0xC200, 0x10000, 0x0 -> 115200==0x1C200 //0xB0, 0x400, 0x0, 0x0-> 1200==0x4B0 convertedInterger |= maskedShiftedValue; } return convertedInterger; } //convert interger type value to byte array //possible input value: byte/short/int/long //Note: max return byte array is 8 -> max support long public static byte[] integerToByteArr(long inputIntergerValue, int byteLen){ byte[] convertedByteArr = new byte[byteLen]; for (int i = 0; i < convertedByteArr.length; i++) { convertedByteArr[i] = (byte) ((inputIntergerValue >> (8 * i)) & 0xFF); //115200 == [0, -62, 1, 0, 0, 0, 0, 0] //1200==[-80, 4, 0, 0] //600==[88, 2] //32==[32] } return convertedByteArr; } private void verifyConfig(int writtenBaudrate, int writtenLineControl){ //1. verify baudrate byte[] baudrateByteArr = new byte[]{0,0,0,0}; mConnection.controlTransfer(REQTYPE_INTERFACE_TO_HOST, CP210X_GET_BAUDRATE, 0, 0/* index */, baudrateByteArr, 4, USB_CTRL_GET_TIMEOUT_MILLIS); //int readbackBaudrate = (baudrateByteArr[0]) | (baudrateByteArr[1] << 8) | (baudrateByteArr[2] << 16) | (baudrateByteArr[3] << 24); //int readbackBaudrate= (baudrateByteArr[3]<<24)&0xff000000|(baudrateByteArr[2]<<16)&0xff0000|(baudrateByteArr[1]<<8)&0xff00|(baudrateByteArr[0]<<0)&0xff; int readbackBaudrate = (int)byteArrToInteger(baudrateByteArr); if(writtenBaudrate == readbackBaudrate){ //ok } else{ //false } //2.verify other config byte[] lineControlByteArr = new byte[]{0,0}; mConnection.controlTransfer(REQTYPE_INTERFACE_TO_HOST, CP210X_GET_LINE_CTL, 0, 0/* index */, lineControlByteArr, 2, USB_CTRL_GET_TIMEOUT_MILLIS); //int readbackLineControl = (lineControlByteArr[0]) | (lineControlByteArr[1] << 8); int readbackLineControl = (int)byteArrToInteger(lineControlByteArr); if(writtenLineControl == readbackLineControl){ //ok } else{ //false } } @Override public boolean getCD() throws IOException { return false; } @Override public boolean getCTS() throws IOException { return false; } @Override public boolean getDSR() throws IOException { return false; } @Override public boolean getDTR() throws IOException { return mDtr; //return true; } @Override public void setDTR(boolean value) throws IOException { mDtr = value; short control = 0; if (mDtr) { control |= CONTROL_DTR; control |= CONTROL_WRITE_DTR; } else{ control &= ~CONTROL_DTR; control |= CONTROL_WRITE_DTR; } try { cp210x_set_config_single(CP210X_SET_MHS, control); verifyRtsDtr(control); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean getRI() throws IOException { return false; } @Override public boolean getRTS() throws IOException { return mRts; //return true; } @Override public void setRTS(boolean value) throws IOException { mRts = value; short control = 0; if (mRts) { control |= CONTROL_RTS; control |= CONTROL_WRITE_RTS; } else { control &= ~CONTROL_RTS; control |= CONTROL_WRITE_RTS; } try { cp210x_set_config_single(CP210X_SET_MHS, control); verifyRtsDtr(control); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /* // set/clear RTS/CTS and DTR/DSR private void setDtrRts() { short control = 0; if (mRts) { control |= CONTROL_RTS; control |= CONTROL_WRITE_RTS; } else { control &= ~CONTROL_RTS; control |= CONTROL_WRITE_RTS; } if (mDtr) { control |= CONTROL_DTR; control |= CONTROL_WRITE_DTR; } else{ control &= ~CONTROL_DTR; control |= CONTROL_WRITE_DTR; } try { cp210x_set_config_single(CP210X_SET_MHS, control); verifyRtsDtr(control); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } */ private void verifyRtsDtr(int writtenMhsControl){ //1. verify RTS DTR int writtenControlValue = writtenMhsControl & 0xFF; // only lowest 8 bit used for indicate RTS, DTR, ... // byte[] mhsControlByteArr = new byte[]{0}; byte[] mhsControlByteArr = new byte[]{0}; // so here only need to read 1 byte mConnection.controlTransfer(REQTYPE_INTERFACE_TO_HOST, CP210X_GET_MDMSTS, 0, 0/* index */, mhsControlByteArr, mhsControlByteArr.length, USB_CTRL_GET_TIMEOUT_MILLIS); int readbackMhsControl = (int)byteArrToInteger(mhsControlByteArr); //seem here can not verify written ok or not //for those bit not reflect whether happen RTS or DTR if(writtenControlValue == readbackMhsControl){ //ok //written 769==0x301 -> read back: 0x01 => OK //higher bits auto become 0 after written } else{ //false } } public static Map<Integer, int[]> getSupportedDevices() { final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILAB), new int[] { UsbId.SILAB_CP210X_DEFAULT_0, UsbId.SILAB_CP210X_DEFAULT_1, UsbId.SILAB_CP210X_DEFAULT_2, UsbId.SILAB_CP210X_DEFAULT_3 }); return supportedDevices; } /* * cp210x_quantise_baudrate * Quantises the baud rate as per AN205 Table 1 */ private int cp210x_quantise_baudrate(int baud) { if (baud <= 300) baud = 300; else if (baud <= 600) baud = 600; else if (baud <= 1200) baud = 1200; else if (baud <= 1800) baud = 1800; else if (baud <= 2400) baud = 2400; else if (baud <= 4000) baud = 4000; else if (baud <= 4803) baud = 4800; else if (baud <= 7207) baud = 7200; else if (baud <= 9612) baud = 9600; else if (baud <= 14428) baud = 14400; else if (baud <= 16062) baud = 16000; else if (baud <= 19250) baud = 19200; else if (baud <= 28912) baud = 28800; else if (baud <= 38601) baud = 38400; else if (baud <= 51558) baud = 51200; else if (baud <= 56280) baud = 56000; else if (baud <= 58053) baud = 57600; else if (baud <= 64111) baud = 64000; else if (baud <= 77608) baud = 76800; else if (baud <= 117028) baud = 115200; else if (baud <= 129347) baud = 128000; else if (baud <= 156868) baud = 153600; else if (baud <= 237832) baud = 230400; else if (baud <= 254234) baud = 250000; else if (baud <= 273066) baud = 256000; else if (baud <= 491520) baud = 460800; else if (baud <= 567138) baud = 500000; else if (baud <= 670254) baud = 576000; else if (baud < 1000000) baud = 921600; else if (baud > 2000000) baud = 2000000; return baud; } /* * CP2101 supports the following baud rates: * * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800, * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600 * * CP2102 and CP2103 support the following additional rates: * * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000, * 576000 * * The device will map a requested rate to a supported one, but the result * of requests for rates greater than 1053257 is undefined (see AN205). * * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud, * respectively, with an error less than 1%. The actual rates are determined * by * * div = round(freq / (2 x prescale x request)) * actual = freq / (2 x prescale x div) * * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps * or 1 otherwise. * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1 * otherwise. */ private void cp210x_change_speed(int baudrate) throws IOException { // byte[] rawData = new byte[4]; // // for (int i = 0; i < rawData.length; i++) { // rawData[i] = (byte) ((baudrate >> (8 * i)) & 0xFF); // } // // cp210x_set_config(CP210X_SET_BAUDRATE, 0x0000, rawData, rawData.length); byte[] baudrateByteArr = integerToByteArr(baudrate, 4); cp210x_set_config(CP210X_SET_BAUDRATE, 0x0000, baudrateByteArr, baudrateByteArr.length); } }
调试结果是:
verifyConfig和verifyRtsDtr
都验证通过了。
但是结果最后HART猫还是无法从HART设备上读取信息,
发送对应的command 0,还是没有对应的返回信息。
14.试试去改为:
//private static final boolean ENABLE_ASYNC_READS = true; private static final boolean ENABLE_ASYNC_READS = false;
看看效果,结果还是不行。
暂时就这样了。
等以后再说吧。
【总结】
目前结果是:
根据已有资料,基本确定了:
配置baudrate和其他config,以及设置RTS,DTR等动作,都是成功配置的。
但是目前还是不知道:
为何USB HART猫,此处最终没有成功的和HART设备通信。
可能的原因:
1.android的app中的代码有问题。
2.本身此处的USB HART猫,就是不能很好的支持此处通过代码配置RTS,DTR的形式去和物理上的HART设备通信,而无法获得对应的command 0的返回值的。
3.其他未知原因。
【后记】
1.后来看到:
提到了:
CP2102的write有问题。
所以,此处我这里HART不工作,估计就是和此write不工作有关,导致我的command 0的数据,实际没有真正写下去,没写到HART设备中。
注:
不过,对于ExSaf的ESH232U的TXD的指示灯,当我发送write时,是正常可以闪的,说明是:
代码的write真正执行到了,且也通过HART猫去发送数据了,但是实际上由于上面说的write底层有问题,导致无法反正正确的数据。
另外:
另外一个,正常工作的HART猫,是可以的。
其物理连接是:USB转串口:FTDI的FT232R + RS232接口的HART猫:Exsaf ESH232R
2.所以,目前基本确定:
应该是由于
UsbSerialDriver.write() or SerialInputOutputManager.writeAsync()
不工作,导致此处HART猫不工作的。
所以:
此处,没有足够的设备和方法去调试,暂时无法通过个人解决此问题。
希望作者有空帮忙解决。
【后记 2013-11-28】
1.忘了记录于此了:
之前调试android的apk期间,记录的,该usb hart猫的vid和pid,记录与此:
UsbDevice[mName=/dev/bus/usb/001/018,mVendorId=4292,mProductId=60000,mClass=0,mSubclass=0,mProtocol=0,mInterfaces=[Landroid.os.Parcelable;@414efa70] 4292=0x10c4 60000=0xEA60 |
供以后需要时参考。
转载请注明:在路上 » 【记录】给usb-serial-for-android中的Silicon Labs的CP2102中添加RTS和DTR的支持