mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-31 10:27:27 +00:00 
			
		
		
		
	support ft_232h, cp210_ multiport devices
harmonize claimInterface() error handling cancel read() on close()
This commit is contained in:
		
							parent
							
								
									0ea5b282b7
								
							
						
					
					
						commit
						61b272b8b6
					
				
							
								
								
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
								
							| @ -1 +0,0 @@ | ||||
| usb-serial-for-android | ||||
							
								
								
									
										21
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										21
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
								
							| @ -1,21 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <component name="CompilerConfiguration"> | ||||
|     <resourceExtensions /> | ||||
|     <wildcardResourcePatterns> | ||||
|       <entry name="!?*.java" /> | ||||
|       <entry name="!?*.form" /> | ||||
|       <entry name="!?*.class" /> | ||||
|       <entry name="!?*.groovy" /> | ||||
|       <entry name="!?*.scala" /> | ||||
|       <entry name="!?*.flex" /> | ||||
|       <entry name="!?*.kt" /> | ||||
|       <entry name="!?*.clj" /> | ||||
|     </wildcardResourcePatterns> | ||||
|     <annotationProcessing> | ||||
|       <profile default="true" name="Default" enabled="false"> | ||||
|         <processorPath useClasspath="true" /> | ||||
|       </profile> | ||||
|     </annotationProcessing> | ||||
|   </component> | ||||
| </project> | ||||
							
								
								
									
										3
									
								
								.idea/copyright/profiles_settings.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								.idea/copyright/profiles_settings.xml
									
									
									
										generated
									
									
									
								
							| @ -1,3 +0,0 @@ | ||||
| <component name="CopyrightManager"> | ||||
|   <settings default="" /> | ||||
| </component> | ||||
							
								
								
									
										25
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										25
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							| @ -5,11 +5,12 @@ | ||||
|     <option name="myDefaultNotNull" value="android.support.annotation.NonNull" /> | ||||
|     <option name="myNullables"> | ||||
|       <value> | ||||
|         <list size="4"> | ||||
|         <list size="5"> | ||||
|           <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" /> | ||||
|           <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" /> | ||||
|           <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" /> | ||||
|           <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" /> | ||||
|           <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" /> | ||||
|           <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" /> | ||||
|           <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" /> | ||||
|         </list> | ||||
|       </value> | ||||
|     </option> | ||||
| @ -24,26 +25,10 @@ | ||||
|       </value> | ||||
|     </option> | ||||
|   </component> | ||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | ||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | ||||
|     <output url="file://$PROJECT_DIR$/build/classes" /> | ||||
|   </component> | ||||
|   <component name="ProjectType"> | ||||
|     <option name="id" value="Android" /> | ||||
|   </component> | ||||
|   <component name="masterDetails"> | ||||
|     <states> | ||||
|       <state key="ProjectJDKs.UI"> | ||||
|         <settings> | ||||
|           <last-edited>1.8</last-edited> | ||||
|           <splitter-proportions> | ||||
|             <option name="proportions"> | ||||
|               <list> | ||||
|                 <option value="0.2" /> | ||||
|               </list> | ||||
|             </option> | ||||
|           </splitter-proportions> | ||||
|         </settings> | ||||
|       </state> | ||||
|     </states> | ||||
|   </component> | ||||
| </project> | ||||
| @ -6,7 +6,7 @@ buildscript { | ||||
|         google() | ||||
|     } | ||||
|     dependencies { | ||||
|         classpath 'com.android.tools.build:gradle:3.1.1' | ||||
|         classpath 'com.android.tools.build:gradle:3.1.2' | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| apply plugin: 'com.android.application' | ||||
| 
 | ||||
| android { | ||||
|     compileSdkVersion 26 | ||||
|     compileSdkVersion 27 | ||||
|     buildToolsVersion '27.0.3' | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion 14 | ||||
|         targetSdkVersion 26 | ||||
|         targetSdkVersion 27 | ||||
| 
 | ||||
|         testInstrumentationRunner "android.test.InstrumentationTestRunner" | ||||
|     } | ||||
|  | ||||
| @ -3,12 +3,12 @@ apply plugin: 'maven' | ||||
| apply plugin: 'signing' | ||||
| 
 | ||||
| android { | ||||
|     compileSdkVersion 26 | ||||
|     compileSdkVersion 27 | ||||
|     buildToolsVersion '27.0.3' | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion 14 | ||||
|         targetSdkVersion 26 | ||||
|         targetSdkVersion 27 | ||||
|         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||||
|     } | ||||
| 
 | ||||
| @ -23,7 +23,7 @@ android { | ||||
| dependencies { | ||||
|     testImplementation 'junit:junit:4.12' | ||||
|     androidTestImplementation 'com.android.support:support-annotations:27.1.1' | ||||
|     androidTestImplementation 'com.android.support.test:runner:1.0.1' | ||||
|     androidTestImplementation 'com.android.support.test:runner:1.0.2' | ||||
|     androidTestImplementation 'commons-net:commons-net:3.6' | ||||
|     androidTestImplementation 'org.apache.commons:commons-lang3:3.7' | ||||
| } | ||||
|  | ||||
| @ -79,10 +79,12 @@ import static org.junit.Assert.fail; | ||||
| @RunWith(AndroidJUnit4.class) | ||||
| public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
| 
 | ||||
|     // configuration: | ||||
|     private final static String  rfc2217_server_host = "192.168.0.100"; | ||||
|     private final static int     rfc2217_server_port = 2217; | ||||
|     private final static boolean rfc2217_server_nonstandard_baudrates = false; // false on Windows, Raspi | ||||
|     private final static boolean rfc2217_server_parity_mark_space = false; // false on Raspi | ||||
|     private final static int     test_device_port = 0; | ||||
| 
 | ||||
|     private final static int     TELNET_READ_WAIT = 500; | ||||
|     private final static int     USB_READ_WAIT    = 500; | ||||
| @ -110,6 +112,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|     private static OutputStream telnetWriteStream; | ||||
|     private static Integer[] telnetComPortOptionCounter = {0}; | ||||
|     private int telnetWriteDelay = 0; | ||||
|     private boolean isCp21xxRestrictedPort = false; // second port of Cp2105 has limited dataBits, stopBits, parity | ||||
| 
 | ||||
|     @BeforeClass | ||||
|     public static void setUpFixture() throws Exception { | ||||
| @ -149,10 +152,10 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|         List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager); | ||||
|         assertEquals("no usb device found", 1, availableDrivers.size()); | ||||
|         usbSerialDriver = availableDrivers.get(0); | ||||
|         assertEquals(1, usbSerialDriver.getPorts().size()); | ||||
|         usbSerialPort = usbSerialDriver.getPorts().get(0); | ||||
|         assertTrue( usbSerialDriver.getPorts().size() > test_device_port); | ||||
|         usbSerialPort = usbSerialDriver.getPorts().get(test_device_port); | ||||
|         Log.i(TAG, "Using USB device "+ usbSerialDriver.getClass().getSimpleName()); | ||||
| 
 | ||||
|         isCp21xxRestrictedPort = usbSerialDriver instanceof Cp21xxSerialDriver && usbSerialDriver.getPorts().size()==2 && test_device_port == 1; | ||||
| 
 | ||||
|         if (!usbManager.hasPermission(usbSerialPort.getDriver().getDevice())) { | ||||
|             final Boolean[] granted = {Boolean.FALSE}; | ||||
| @ -432,6 +435,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|                 ; // todo: add range check in driver | ||||
|             else | ||||
|                 fail("invalid baudrate 0"); | ||||
|         } catch (java.io.IOException e) { // cp2105 second port | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|         } | ||||
|         try { | ||||
| @ -445,6 +449,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             else | ||||
|                 fail("invalid baudrate 0"); | ||||
|         } catch (java.lang.ArithmeticException e) { // ch340 | ||||
|         } catch (java.io.IOException e) { // cp2105 second port | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|         } | ||||
|         try { | ||||
| @ -473,12 +478,21 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             else | ||||
|                 fail("invalid baudrate 2^31"); | ||||
|         } catch (java.lang.ArithmeticException e) { // ch340 | ||||
|         } catch (java.io.IOException e) { // cp2105 second port | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|         } | ||||
| 
 | ||||
|         for(int baudRate : new int[] {2400, 19200, 42000, 115200} ) { | ||||
|         for(int baudRate : new int[] {300, 2400, 19200, 42000, 115200} ) { | ||||
|             if(baudRate == 42000 && !rfc2217_server_nonstandard_baudrates) | ||||
|                 continue; // rfc2217_server.py would terminate | ||||
|             if(baudRate == 300 && isCp21xxRestrictedPort) { | ||||
|                 try { | ||||
|                     usbParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
|                     assertTrue(false); | ||||
|                 } catch (java.io.IOException e) { | ||||
|                 } | ||||
|                 continue; | ||||
|             } | ||||
|             telnetParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
| 
 | ||||
| @ -543,14 +557,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|         assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff})); | ||||
| 
 | ||||
|         // usb -> telnet | ||||
|         telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
|         usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE); | ||||
|         usbWrite(new byte[] {0x00}); | ||||
|         Thread.sleep(1); | ||||
|         usbWrite(new byte[] {(byte)0xff}); | ||||
|         data = telnetRead(2); | ||||
|         assertThat("19000/7N1", data, equalTo(new byte[] {(byte)0x80, (byte)0xff})); | ||||
| 
 | ||||
|         try { | ||||
|             telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbParameters(19200, 7, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbWrite(new byte[]{0x00}); | ||||
|             Thread.sleep(1); | ||||
|             usbWrite(new byte[]{(byte) 0xff}); | ||||
|             data = telnetRead(2); | ||||
|             assertThat("19000/7N1", data, equalTo(new byte[]{(byte) 0x80, (byte) 0xff})); | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|                 if(!isCp21xxRestrictedPort) | ||||
|                     throw e; | ||||
|         } | ||||
|         try { | ||||
|             usbParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbWrite(new byte[]{0x00}); | ||||
| @ -559,7 +577,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             data = telnetRead(2); | ||||
|             assertThat("19000/6N1", data, equalTo(new byte[]{(byte) 0xc0, (byte) 0xff})); | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|             if (!(usbSerialDriver instanceof FtdiSerialDriver)) | ||||
|             if (!(isCp21xxRestrictedPort || usbSerialDriver instanceof FtdiSerialDriver)) | ||||
|                 throw e; | ||||
|         } | ||||
|         try { | ||||
| @ -570,7 +588,7 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             data = telnetRead(2); | ||||
|             assertThat("19000/5N1", data, equalTo(new byte[] {(byte)0xe0, (byte)0xff})); | ||||
|         } catch (java.lang.IllegalArgumentException e) { | ||||
|             if (!(usbSerialDriver instanceof FtdiSerialDriver)) | ||||
|             if (!(isCp21xxRestrictedPort || usbSerialDriver instanceof FtdiSerialDriver)) | ||||
|                 throw e; | ||||
|         } | ||||
|     } | ||||
| @ -592,6 +610,18 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             } catch (java.lang.IllegalArgumentException e) { | ||||
|             } | ||||
|         } | ||||
|         if(isCp21xxRestrictedPort) { | ||||
|             usbParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbParameters(19200, 8, 1, UsbSerialPort.PARITY_EVEN); | ||||
|             usbParameters(19200, 8, 1, UsbSerialPort.PARITY_ODD); | ||||
|             try { | ||||
|                 usbParameters(19200, 8, 1, UsbSerialPort.PARITY_MARK); | ||||
|                 usbParameters(19200, 8, 1, UsbSerialPort.PARITY_SPACE); | ||||
|             } catch (java.lang.IllegalArgumentException e) { | ||||
|             } | ||||
|             return; | ||||
|             // test below not possible as it requires unsupported 7 dataBits | ||||
|         } | ||||
| 
 | ||||
|         // usb -> telnet | ||||
|         telnetParameters(19200, 8, 1, UsbSerialPort.PARITY_NONE); | ||||
| @ -697,11 +727,16 @@ public class DeviceTest implements SerialInputOutputManager.Listener { | ||||
|             //             1000001 0   10011111 | ||||
|             // in 6N1:    addddddo addddddo | ||||
|             //             100000   110100 | ||||
|             usbParameters(19200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE); | ||||
|             telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE); | ||||
|             usbWrite(new byte[]{(byte)0x41, (byte)0xf9}); | ||||
|             data = telnetRead(2); | ||||
|             assertThat("19200/8N1", data, equalTo(new byte[]{1, 11})); | ||||
|             try { | ||||
|                 usbParameters(19200, 8, UsbSerialPort.STOPBITS_2, UsbSerialPort.PARITY_NONE); | ||||
|                 telnetParameters(19200, 6, 1, UsbSerialPort.PARITY_NONE); | ||||
|                 usbWrite(new byte[]{(byte) 0x41, (byte) 0xf9}); | ||||
|                 data = telnetRead(2); | ||||
|                 assertThat("19200/8N1", data, equalTo(new byte[]{1, 11})); | ||||
|             } catch(java.lang.IllegalArgumentException e) { | ||||
|                 if(!isCp21xxRestrictedPort) | ||||
|                     throw e; | ||||
|             } | ||||
|             // todo: could create similar test for 1.5 stopbits, by reading at double speed | ||||
|             //       but only some devices support 1.5 stopbits and it is basically not used any more | ||||
|         } | ||||
|  | ||||
| @ -84,9 +84,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver { | ||||
| 		private boolean dtr = false; | ||||
| 		private boolean rts = false; | ||||
| 
 | ||||
| 		private final boolean mEnableAsyncReads; | ||||
| 		private final Boolean mEnableAsyncReads; | ||||
| 		private UsbEndpoint mReadEndpoint; | ||||
| 		private UsbEndpoint mWriteEndpoint; | ||||
| 		private UsbRequest mUsbRequest; | ||||
| 
 | ||||
| 		public Ch340SerialPort(UsbDevice device, int portNumber) { | ||||
| 			super(device, portNumber); | ||||
| @ -109,10 +110,8 @@ public class Ch34xSerialDriver implements UsbSerialDriver { | ||||
| 			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"); | ||||
| 					if (!mConnection.claimInterface(usbIface, true)) { | ||||
| 						throw new IOException("Could not claim data interface."); | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| @ -154,7 +153,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver { | ||||
| 			if (mConnection == null) { | ||||
| 				throw new IOException("Already closed"); | ||||
| 			} | ||||
| 
 | ||||
| 			synchronized (mEnableAsyncReads) { | ||||
| 				if (mUsbRequest != null) | ||||
| 					mUsbRequest.cancel(); | ||||
| 			} | ||||
| 			// TODO: nothing sended on close, maybe needed? | ||||
| 
 | ||||
| 			try { | ||||
| @ -175,8 +177,11 @@ public class Ch34xSerialDriver implements UsbSerialDriver { | ||||
| 					if (!request.queue(buf, dest.length)) { | ||||
| 						throw new IOException("Error queueing request."); | ||||
| 					} | ||||
| 
 | ||||
| 					mUsbRequest = request; | ||||
| 					final UsbRequest response = mConnection.requestWait(); | ||||
| 					synchronized (mEnableAsyncReads) { | ||||
| 						mUsbRequest = null; | ||||
| 					} | ||||
| 					if (response == null) { | ||||
| 						throw new IOException("Null response"); | ||||
| 					} | ||||
| @ -189,6 +194,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver { | ||||
| 						return 0; | ||||
| 					} | ||||
| 				} finally { | ||||
| 					mUsbRequest = null; | ||||
| 					request.close(); | ||||
| 				} | ||||
| 			} else { | ||||
|  | ||||
| @ -32,7 +32,7 @@ import android.util.Log; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.Collections; | ||||
| import java.util.ArrayList; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @ -42,11 +42,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|     private static final String TAG = Cp21xxSerialDriver.class.getSimpleName(); | ||||
| 
 | ||||
|     private final UsbDevice mDevice; | ||||
|     private final UsbSerialPort mPort; | ||||
|     private final List<UsbSerialPort> mPorts; | ||||
| 
 | ||||
|     public Cp21xxSerialDriver(UsbDevice device) { | ||||
|         mDevice = device; | ||||
|         mPort = new Cp21xxSerialPort(mDevice, 0); | ||||
|         mPorts = new ArrayList<>(); | ||||
|         for( int port = 0; port < device.getInterfaceCount(); port++) { | ||||
|             mPorts.add(new Cp21xxSerialPort(mDevice, port)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @ -56,7 +59,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|     @Override | ||||
|     public List<UsbSerialPort> getPorts() { | ||||
|         return Collections.singletonList(mPort); | ||||
|         return mPorts; | ||||
|     } | ||||
| 
 | ||||
|     public class Cp21xxSerialPort extends CommonUsbSerialPort { | ||||
| @ -104,9 +107,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|         private static final int CONTROL_WRITE_DTR = 0x0100; | ||||
|         private static final int CONTROL_WRITE_RTS = 0x0200; | ||||
| 
 | ||||
|         private final boolean mEnableAsyncReads; | ||||
|         private final Boolean mEnableAsyncReads; | ||||
|         private UsbEndpoint mReadEndpoint; | ||||
|         private UsbEndpoint mWriteEndpoint; | ||||
|         private UsbRequest mUsbRequest; | ||||
| 
 | ||||
|         // second port of Cp2105 has limited baudRate, dataBits, stopBits, parity | ||||
|         // unsupported baudrate returns error at controlTransfer(), other parameters are silently ignored | ||||
|         private boolean mIsRestrictedPort; | ||||
| 
 | ||||
|         public Cp21xxSerialPort(UsbDevice device, int portNumber) { | ||||
|             super(device, portNumber); | ||||
| @ -120,7 +128,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         private int setConfigSingle(int request, int value) { | ||||
|             return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value, | ||||
|                     0, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                     mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
| @ -131,17 +139,15 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|             mConnection = connection; | ||||
|             boolean opened = false; | ||||
|             mIsRestrictedPort = mDevice.getInterfaceCount() == 2 && mPortNumber == 1; | ||||
|             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"); | ||||
|                     } | ||||
|                 if(mPortNumber >= mDevice.getInterfaceCount()) { | ||||
|                     throw new IOException("Unknown port number"); | ||||
|                 } | ||||
|                 UsbInterface dataIface = mDevice.getInterface(mPortNumber); | ||||
|                 if (!mConnection.claimInterface(dataIface, true)) { | ||||
|                     throw new IOException("Could not claim interface " + mPortNumber); | ||||
|                 } | ||||
| 
 | ||||
|                 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) { | ||||
| @ -174,6 +180,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|             if (mConnection == null) { | ||||
|                 throw new IOException("Already closed"); | ||||
|             } | ||||
|             synchronized (mEnableAsyncReads) { | ||||
|                 if(mUsbRequest != null) { | ||||
|                     mUsbRequest.cancel(); | ||||
|                 } | ||||
|             } | ||||
|             try { | ||||
|                 setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE); | ||||
|                 mConnection.close(); | ||||
| @ -192,8 +203,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|                     if (!request.queue(buf, dest.length)) { | ||||
|                         throw new IOException("Error queueing request."); | ||||
|                     } | ||||
| 
 | ||||
|                     mUsbRequest = request; | ||||
|                     final UsbRequest response = mConnection.requestWait(); | ||||
|                     synchronized (mEnableAsyncReads) { | ||||
|                         mUsbRequest = null; | ||||
|                     } | ||||
|                     if (response == null) { | ||||
|                         throw new IOException("Null response"); | ||||
|                     } | ||||
| @ -206,6 +220,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|                         return 0; | ||||
|                     } | ||||
|                 } finally { | ||||
|                     mUsbRequest = null; | ||||
|                     request.close(); | ||||
|                 } | ||||
|             } else { | ||||
| @ -269,7 +284,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|                     (byte) ((baudRate >> 24) & 0xff) | ||||
|             }; | ||||
|             int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE, | ||||
|                     0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                     0, mPortNumber, data, 4, USB_WRITE_TIMEOUT_MILLIS); | ||||
|             if (ret < 0) { | ||||
|                 throw new IOException("Error setting baud rate."); | ||||
|             } | ||||
| @ -283,12 +298,18 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|             int configDataBits = 0; | ||||
|             switch (dataBits) { | ||||
|                 case DATABITS_5: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits); | ||||
|                     configDataBits |= 0x0500; | ||||
|                     break; | ||||
|                 case DATABITS_6: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits); | ||||
|                     configDataBits |= 0x0600; | ||||
|                     break; | ||||
|                 case DATABITS_7: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits); | ||||
|                     configDataBits |= 0x0700; | ||||
|                     break; | ||||
|                 case DATABITS_8: | ||||
| @ -308,9 +329,13 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|                     configDataBits |= 0x0020; | ||||
|                     break; | ||||
|                 case PARITY_MARK: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported parity value: mark"); | ||||
|                     configDataBits |= 0x0030; | ||||
|                     break; | ||||
|                 case PARITY_SPACE: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported parity value: space"); | ||||
|                     configDataBits |= 0x0040; | ||||
|                     break; | ||||
|                 default: | ||||
| @ -323,6 +348,8 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||
|                 case STOPBITS_1_5: | ||||
|                     throw new IllegalArgumentException("Unsupported stopBits value: 1.5"); | ||||
|                 case STOPBITS_2: | ||||
|                     if(mIsRestrictedPort) | ||||
|                         throw new IllegalArgumentException("Unsupported stopBits value: 2"); | ||||
|                     configDataBits |= 2; | ||||
|                     break; | ||||
|                 default: | ||||
|  | ||||
| @ -29,11 +29,9 @@ import android.hardware.usb.UsbRequest; | ||||
| import android.os.Build; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import com.hoho.android.usbserial.util.HexDump; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.Collections; | ||||
| import java.util.ArrayList; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @ -73,6 +71,8 @@ import java.util.Map; | ||||
|  * Supported and tested devices: | ||||
|  * <ul> | ||||
|  * <li>{@value DeviceType#TYPE_R}</li> | ||||
|  * <li>{@value DeviceType#TYPE_2232H}</li> | ||||
|  * <li>{@value DeviceType#TYPE_4232H}</li> | ||||
|  * </ul> | ||||
|  * </p> | ||||
|  * <p> | ||||
| @ -80,8 +80,6 @@ import java.util.Map; | ||||
|  * feedback or patches): | ||||
|  * <ul> | ||||
|  * <li>{@value DeviceType#TYPE_2232C}</li> | ||||
|  * <li>{@value DeviceType#TYPE_2232H}</li> | ||||
|  * <li>{@value DeviceType#TYPE_4232H}</li> | ||||
|  * <li>{@value DeviceType#TYPE_AM}</li> | ||||
|  * <li>{@value DeviceType#TYPE_BM}</li> | ||||
|  * </ul> | ||||
| @ -96,7 +94,7 @@ import java.util.Map; | ||||
| public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|     private final UsbDevice mDevice; | ||||
|     private final UsbSerialPort mPort; | ||||
|     private final List<UsbSerialPort> mPorts; | ||||
| 
 | ||||
|     /** | ||||
|      * FTDI chip types. | ||||
| @ -107,8 +105,12 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|     public FtdiSerialDriver(UsbDevice device) { | ||||
|         mDevice = device; | ||||
|         mPort = new FtdiSerialPort(mDevice, 0); | ||||
|         mPorts = new ArrayList<>(); | ||||
|         for( int port = 0; port < device.getInterfaceCount(); port++) { | ||||
|             mPorts.add(new FtdiSerialPort(mDevice, port)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public UsbDevice getDevice() { | ||||
|         return mDevice; | ||||
| @ -116,7 +118,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|     @Override | ||||
|     public List<UsbSerialPort> getPorts() { | ||||
|         return Collections.singletonList(mPort); | ||||
|         return mPorts; | ||||
|     } | ||||
| 
 | ||||
|     private class FtdiSerialPort extends CommonUsbSerialPort { | ||||
| @ -182,9 +184,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         private DeviceType mType; | ||||
| 
 | ||||
|         private int mInterface = 0; /* INTERFACE_ANY */ | ||||
| 
 | ||||
|         private int mMaxPacketSize = 64; // TODO(mikey): detect | ||||
|         private int mIndex = 0; | ||||
| 
 | ||||
|         /** | ||||
|          * Due to http://b.android.com/28023 , we cannot use UsbRequest async reads | ||||
| @ -230,14 +230,21 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
|         } | ||||
| 
 | ||||
|         public void reset() throws IOException { | ||||
|             // TODO(mikey): autodetect. | ||||
|             mType = DeviceType.TYPE_R; | ||||
|             if(mDevice.getInterfaceCount() > 1) { | ||||
|                 mIndex = mPortNumber + 1; | ||||
|                 if (mDevice.getInterfaceCount() == 2) | ||||
|                     mType = DeviceType.TYPE_2232H; | ||||
|                 if (mDevice.getInterfaceCount() == 4) | ||||
|                     mType = DeviceType.TYPE_4232H; | ||||
|             } | ||||
| 
 | ||||
|             int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, | ||||
|                     SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                     SIO_RESET_SIO, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|             if (result != 0) { | ||||
|                 throw new IOException("Reset failed: result=" + result); | ||||
|             } | ||||
| 
 | ||||
|             // TODO(mikey): autodetect. | ||||
|             mType = DeviceType.TYPE_R; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
| @ -249,12 +256,10 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|             boolean opened = false; | ||||
|             try { | ||||
|                 for (int i = 0; i < mDevice.getInterfaceCount(); i++) { | ||||
|                     if (connection.claimInterface(mDevice.getInterface(i), true)) { | ||||
|                         Log.d(TAG, "claimInterface " + i + " SUCCESS"); | ||||
|                     } else { | ||||
|                         throw new IOException("Error claiming interface " + i); | ||||
|                     } | ||||
|                 if (connection.claimInterface(mDevice.getInterface(mPortNumber), true)) { | ||||
|                     Log.d(TAG, "claimInterface " + mPortNumber + " SUCCESS"); | ||||
|                 } else { | ||||
|                     throw new IOException("Error claiming interface " + mPortNumber); | ||||
|                 } | ||||
|                 reset(); | ||||
|                 opened = true; | ||||
| @ -280,7 +285,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         @Override | ||||
|         public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||
|             final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0); | ||||
|             final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0); | ||||
| 
 | ||||
|             if (mEnableAsyncReads) { | ||||
|                 final UsbRequest request = new UsbRequest(); | ||||
| @ -325,7 +330,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|         @Override | ||||
|         public int write(byte[] src, int timeoutMillis) throws IOException { | ||||
|             final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1); | ||||
|             final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1); | ||||
|             int offset = 0; | ||||
| 
 | ||||
|             while (offset < src.length) { | ||||
| @ -425,7 +430,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
|             } | ||||
| 
 | ||||
|             int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, | ||||
|                     SIO_SET_DATA_REQUEST, config, 0 /* index */, | ||||
|                     SIO_SET_DATA_REQUEST, config, mIndex, | ||||
|                     null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|             if (result != 0) { | ||||
|                 throw new IOException("Setting parameters failed: result=" + result); | ||||
| @ -505,9 +510,8 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
|             long index; | ||||
|             if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H | ||||
|                     || mType == DeviceType.TYPE_4232H) { | ||||
|                 index = (encodedDivisor >> 8) & 0xffff; | ||||
|                 index &= 0xFF00; | ||||
|                 index |= 0 /* TODO mIndex */; | ||||
|                 index = (encodedDivisor >> 8) & 0xff00; | ||||
|                 index |= mIndex; | ||||
|             } else { | ||||
|                 index = (encodedDivisor >> 16) & 0xffff; | ||||
|             } | ||||
| @ -560,7 +564,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
|         public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException { | ||||
|             if (purgeReadBuffers) { | ||||
|                 int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, | ||||
|                         SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                         SIO_RESET_PURGE_RX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                 if (result != 0) { | ||||
|                     throw new IOException("Flushing RX failed: result=" + result); | ||||
|                 } | ||||
| @ -568,7 +572,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
| 
 | ||||
|             if (purgeWriteBuffers) { | ||||
|                 int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, | ||||
|                         SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                         SIO_RESET_PURGE_TX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||
|                 if (result != 0) { | ||||
|                     throw new IOException("Flushing RX failed: result=" + result); | ||||
|                 } | ||||
| @ -582,6 +586,9 @@ public class FtdiSerialDriver implements UsbSerialDriver { | ||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI), | ||||
|                 new int[] { | ||||
|                     UsbId.FTDI_FT232R, | ||||
|                     UsbId.FTDI_FT232H, | ||||
|                     UsbId.FTDI_FT2232H, | ||||
|                     UsbId.FTDI_FT4232H, | ||||
|                     UsbId.FTDI_FT231X, | ||||
|                 }); | ||||
|         return supportedDevices; | ||||
|  | ||||
| @ -33,6 +33,9 @@ public final class UsbId { | ||||
| 
 | ||||
|     public static final int VENDOR_FTDI = 0x0403; | ||||
|     public static final int FTDI_FT232R = 0x6001; | ||||
|     public static final int FTDI_FT2232H = 0x6010; | ||||
|     public static final int FTDI_FT4232H = 0x6011; | ||||
|     public static final int FTDI_FT232H = 0x6014; | ||||
|     public static final int FTDI_FT231X = 0x6015; | ||||
| 
 | ||||
|     public static final int VENDOR_ATMEL = 0x03EB; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user