mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 02:17:23 +00:00 
			
		
		
		
	added support for cp2102 device
This commit is contained in:
		
							parent
							
								
									c3ac464ab3
								
							
						
					
					
						commit
						2b3528b425
					
				| @ -9,4 +9,7 @@ | ||||
|     <!-- 0x16C0 / 0x0483: Teensyduino  --> | ||||
|     <usb-device vendor-id="5824" product-id="1155" /> | ||||
| 
 | ||||
|     <!-- 0x10C4 / 0xEA60: CP210x UART Bridge --> | ||||
|     <usb-device vender-id="4292" product-id="60000" /> | ||||
|      | ||||
| </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 LEAFLABS_MAPLE = 0x0004; | ||||
|      | ||||
|     public static final int VENDOR_SILAB = 0x10c4; | ||||
|     public static final int SILAB_CP2102 = 0xea60; | ||||
| 
 | ||||
|     private UsbId() { | ||||
|         throw new IllegalAccessError("Non-instantiable class."); | ||||
|     } | ||||
|  | ||||
| @ -67,6 +67,20 @@ public enum UsbSerialProber { | ||||
|             } | ||||
|             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