mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-30 18:07:21 +00:00 
			
		
		
		
	added support for cp2102 device
This commit is contained in:
		
							parent
							
								
									c3ac464ab3
								
							
						
					
					
						commit
						2b3528b425
					
				| @ -9,4 +9,7 @@ | |||||||
|     <!-- 0x16C0 / 0x0483: Teensyduino  --> |     <!-- 0x16C0 / 0x0483: Teensyduino  --> | ||||||
|     <usb-device vendor-id="5824" product-id="1155" /> |     <usb-device vendor-id="5824" product-id="1155" /> | ||||||
| 
 | 
 | ||||||
|  |     <!-- 0x10C4 / 0xEA60: CP210x UART Bridge --> | ||||||
|  |     <usb-device vender-id="4292" product-id="60000" /> | ||||||
|  |      | ||||||
| </resources> | </resources> | ||||||
|  | |||||||
| @ -0,0 +1,275 @@ | |||||||
|  | package com.hoho.android.usbserial.driver; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | public class Cp2102SerialDriver extends UsbSerialDriver { | ||||||
|  |      | ||||||
|  |     private static final String TAG = Cp2102SerialDriver.class.getSimpleName(); | ||||||
|  |      | ||||||
|  |     private static final int DEFAULT_BAUD_RATE = 9600; | ||||||
|  |      | ||||||
|  |     private static final int USB_WRITE_TIMEOUT_MILLIS = 5000; | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      * Configuration Request Types | ||||||
|  |      */ | ||||||
|  |     private static final int REQTYPE_HOST_TO_DEVICE = 0x41; | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      * Configuration Request Codes | ||||||
|  |      */ | ||||||
|  |     private static final int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00; | ||||||
|  |     private static final int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01; | ||||||
|  |     private static final int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03; | ||||||
|  |     private static final int SILABSER_SET_MHS_REQUEST_CODE = 0x07; | ||||||
|  |     private static final int SILABSER_SET_BAUDRATE = 0x1E; | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      * SILABSER_IFC_ENABLE_REQUEST_CODE | ||||||
|  |      */ | ||||||
|  |     private static final int UART_ENABLE = 0x0001; | ||||||
|  |     private static final int UART_DISABLE = 0x0000; | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      * SILABSER_SET_BAUDDIV_REQUEST_CODE | ||||||
|  |      */ | ||||||
|  |     private static final int BAUD_RATE_GEN_FREQ = 0x384000; | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      * SILABSER_SET_MHS_REQUEST_CODE | ||||||
|  |      */ | ||||||
|  |     private static final int MCR_DTR = 0x0001; | ||||||
|  |     private static final int MCR_RTS = 0x0002; | ||||||
|  |     private static final int MCR_ALL = 0x0003; | ||||||
|  |      | ||||||
|  |     private static final int CONTROL_WRITE_DTR = 0x0100; | ||||||
|  |     private static final int CONTROL_WRITE_RTS = 0x0200;     | ||||||
|  | 
 | ||||||
|  |     private UsbEndpoint mReadEndpoint; | ||||||
|  |     private UsbEndpoint mWriteEndpoint;  | ||||||
|  |      | ||||||
|  |     public Cp2102SerialDriver(UsbDevice device, UsbDeviceConnection connection) { | ||||||
|  |         super(device, connection); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     private int setConfigSingle(int request, int value) { | ||||||
|  |         return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,  | ||||||
|  |                 0, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void open() throws IOException {         | ||||||
|  |         boolean opened = false; | ||||||
|  |         try { | ||||||
|  |             for (int i = 0; i < mDevice.getInterfaceCount(); i++) {                 | ||||||
|  |                 UsbInterface usbIface = mDevice.getInterface(i); | ||||||
|  |                 if (mConnection.claimInterface(usbIface, true)) { | ||||||
|  |                     Log.d(TAG, "claimInterface " + i + " SUCCESS");                     | ||||||
|  |                 } else { | ||||||
|  |                     Log.d(TAG, "claimInterface " + i + " FAIL"); | ||||||
|  |                 } | ||||||
|  |             }                        | ||||||
|  |              | ||||||
|  |             UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1); | ||||||
|  |             for (int i = 0; i < dataIface.getEndpointCount(); i++) { | ||||||
|  |                 UsbEndpoint ep = dataIface.getEndpoint(i); | ||||||
|  |                 if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { | ||||||
|  |                     if (ep.getDirection() == UsbConstants.USB_DIR_IN) { | ||||||
|  |                         mReadEndpoint = ep; | ||||||
|  |                     } else { | ||||||
|  |                         mWriteEndpoint = ep; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE); | ||||||
|  |             setConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS); | ||||||
|  |             setConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);             | ||||||
|  | //            setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY); | ||||||
|  |             opened = true; | ||||||
|  |         } finally { | ||||||
|  |             if (!opened) { | ||||||
|  |                 close(); | ||||||
|  |             } | ||||||
|  |         }         | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void close() throws IOException { | ||||||
|  |         setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE); | ||||||
|  |         mConnection.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||||
|  |         final int numBytesRead; | ||||||
|  |         synchronized (mReadBufferLock) { | ||||||
|  |             int readAmt = Math.min(dest.length, mReadBuffer.length); | ||||||
|  |             numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt, | ||||||
|  |                     timeoutMillis); | ||||||
|  |             if (numBytesRead < 0) { | ||||||
|  |                 // This sucks: we get -1 on timeout, not 0 as preferred. | ||||||
|  |                 // We *should* use UsbRequest, except it has a bug/api oversight | ||||||
|  |                 // where there is no way to determine the number of bytes read | ||||||
|  |                 // in response :\ -- http://b.android.com/28023 | ||||||
|  |                 return 0; | ||||||
|  |             } | ||||||
|  |             System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead); | ||||||
|  |         } | ||||||
|  |         return numBytesRead; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @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(mWriteEndpoint, writeBuffer, writeLength, | ||||||
|  |                         timeoutMillis); | ||||||
|  |             } | ||||||
|  |             if (amtWritten <= 0) { | ||||||
|  |                 throw new IOException("Error writing " + writeLength | ||||||
|  |                         + " bytes at offset " + offset + " length=" + src.length); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength); | ||||||
|  |             offset += amtWritten; | ||||||
|  |         } | ||||||
|  |         return offset; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     @Deprecated | ||||||
|  |     public int setBaudRate(int baudRate) throws IOException {    | ||||||
|  |         byte[] data = new byte[] { | ||||||
|  |                 (byte) ( baudRate & 0xff), | ||||||
|  |                 (byte) ((baudRate >> 8 ) & 0xff), | ||||||
|  |                 (byte) ((baudRate >> 16) & 0xff), | ||||||
|  |                 (byte) ((baudRate >> 24) & 0xff) | ||||||
|  |         }; | ||||||
|  |         mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,  | ||||||
|  |                 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |         return baudRate; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void setParameters(int baudRate, int dataBits, int stopBits, int parity) | ||||||
|  |             throws IOException { | ||||||
|  |         setBaudRate(baudRate); | ||||||
|  |                  | ||||||
|  |         int configDataBits = 0; | ||||||
|  |         switch (dataBits) { | ||||||
|  |             case DATABITS_5: | ||||||
|  |                 configDataBits |= 0x0500; | ||||||
|  |                 break; | ||||||
|  |             case DATABITS_6: | ||||||
|  |                 configDataBits |= 0x0600; | ||||||
|  |                 break; | ||||||
|  |             case DATABITS_7: | ||||||
|  |                 configDataBits |= 0x0700; | ||||||
|  |                 break; | ||||||
|  |             case DATABITS_8: | ||||||
|  |                 configDataBits |= 0x0800; | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 configDataBits |= 0x0800; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits); | ||||||
|  | 
 | ||||||
|  |         int configParityBits = 0; // PARITY_NONE | ||||||
|  |         switch (parity) { | ||||||
|  |             case PARITY_ODD: | ||||||
|  |                 configParityBits |= 0x0010; | ||||||
|  |                 break; | ||||||
|  |             case PARITY_EVEN: | ||||||
|  |                 configParityBits |= 0x0020; | ||||||
|  |                 break;             | ||||||
|  |         } | ||||||
|  |         setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configParityBits); | ||||||
|  |          | ||||||
|  |         int configStopBits = 0; | ||||||
|  |         switch (stopBits) { | ||||||
|  |             case STOPBITS_1: | ||||||
|  |                 configStopBits |= 0; | ||||||
|  |                 break; | ||||||
|  |             case STOPBITS_2: | ||||||
|  |                 configStopBits |= 2; | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configStopBits);         | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @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 true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void setDTR(boolean value) throws IOException { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean getRI() throws IOException { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public boolean getRTS() throws IOException { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void setRTS(boolean value) throws IOException { | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     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_CP2102 | ||||||
|  |                 }); | ||||||
|  |         return supportedDevices; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -52,6 +52,9 @@ public final class UsbId { | |||||||
|     public static final int VENDOR_LEAFLABS = 0x1eaf; |     public static final int VENDOR_LEAFLABS = 0x1eaf; | ||||||
|     public static final int LEAFLABS_MAPLE = 0x0004; |     public static final int LEAFLABS_MAPLE = 0x0004; | ||||||
|      |      | ||||||
|  |     public static final int VENDOR_SILAB = 0x10c4; | ||||||
|  |     public static final int SILAB_CP2102 = 0xea60; | ||||||
|  | 
 | ||||||
|     private UsbId() { |     private UsbId() { | ||||||
|         throw new IllegalAccessError("Non-instantiable class."); |         throw new IllegalAccessError("Non-instantiable class."); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -67,6 +67,20 @@ public enum UsbSerialProber { | |||||||
|             } |             } | ||||||
|             return new CdcAcmSerialDriver(usbDevice, connection); |             return new CdcAcmSerialDriver(usbDevice, connection); | ||||||
|         } |         } | ||||||
|  |     }, | ||||||
|  |      | ||||||
|  |     SILAB_SERIAL { | ||||||
|  |         @Override | ||||||
|  |         public UsbSerialDriver getDevice(final UsbManager manager, final UsbDevice usbDevice) { | ||||||
|  |             if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |             final UsbDeviceConnection connection = manager.openDevice(usbDevice); | ||||||
|  |             if (connection == null) { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |             return new Cp2102SerialDriver(usbDevice, connection); | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user