mirror of
				https://github.com/mik3y/usb-serial-for-android
				synced 2025-10-30 18:07:21 +00:00 
			
		
		
		
	Merge branch 'develop'
This commit is contained in:
		
						commit
						4a226864b0
					
				
							
								
								
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,9 +1,21 @@ | |||||||
| UsbSerialLibrary/bin | # Studio/Gradle | ||||||
| UsbSerialLibrary/gen | *.iml | ||||||
|  | .gradle/ | ||||||
|  | build/ | ||||||
|  | 
 | ||||||
|  | # Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067) | ||||||
|  | .idea/workspace.xml | ||||||
|  | .idea/tasks.xml | ||||||
|  | .idea/datasources.xml | ||||||
|  | .idea/dataSources.ids | ||||||
|  | 
 | ||||||
|  | # generated files | ||||||
|  | bin/ | ||||||
|  | gen/ | ||||||
|  | 
 | ||||||
|  | # Eclipse/Android/Misc | ||||||
|  | .metadata/ | ||||||
|  | local.properties | ||||||
|  | *.DS_Store | ||||||
|  | proguard/ | ||||||
| 
 | 
 | ||||||
| UsbSerialExamples/bin |  | ||||||
| UsbSerialExamples/gen |  | ||||||
| UsbSerialLibrary/dictionary.txt |  | ||||||
| UsbSerialLibrary/local.properties |  | ||||||
| UsbSerialLibrary/proguard-project.txt |  | ||||||
| UsbSerialLibrary/build.xml |  | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | usb-serial-for-android | ||||||
							
								
								
									
										23
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="CompilerConfiguration"> | ||||||
|  |     <option name="DEFAULT_COMPILER" value="Javac" /> | ||||||
|  |     <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
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.idea/copyright/profiles_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | <component name="CopyrightManager"> | ||||||
|  |   <settings default="" /> | ||||||
|  | </component> | ||||||
							
								
								
									
										5
									
								
								.idea/encodings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/encodings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> | ||||||
|  | </project> | ||||||
|  | 
 | ||||||
							
								
								
									
										19
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="GradleSettings"> | ||||||
|  |     <option name="linkedExternalProjectsSettings"> | ||||||
|  |       <GradleProjectSettings> | ||||||
|  |         <option name="distributionType" value="DEFAULT_WRAPPED" /> | ||||||
|  |         <option name="externalProjectPath" value="$PROJECT_DIR$" /> | ||||||
|  |         <option name="modules"> | ||||||
|  |           <set> | ||||||
|  |             <option value="$PROJECT_DIR$" /> | ||||||
|  |             <option value="$PROJECT_DIR$/usbSerialExamples" /> | ||||||
|  |             <option value="$PROJECT_DIR$/usbSerialForAndroid" /> | ||||||
|  |           </set> | ||||||
|  |         </option> | ||||||
|  |       </GradleProjectSettings> | ||||||
|  |     </option> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
|  | 
 | ||||||
							
								
								
									
										128
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="DaemonCodeAnalyzer"> | ||||||
|  |     <disable_hints /> | ||||||
|  |   </component> | ||||||
|  |   <component name="ProjectLevelVcsManager" settingsEditedManually="false"> | ||||||
|  |     <OptionsSetting value="true" id="Add" /> | ||||||
|  |     <OptionsSetting value="true" id="Remove" /> | ||||||
|  |     <OptionsSetting value="true" id="Checkout" /> | ||||||
|  |     <OptionsSetting value="true" id="Update" /> | ||||||
|  |     <OptionsSetting value="true" id="Status" /> | ||||||
|  |     <OptionsSetting value="true" id="Edit" /> | ||||||
|  |     <ConfirmationsSetting value="0" id="Add" /> | ||||||
|  |     <ConfirmationsSetting value="0" id="Remove" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="JDK" project-jdk-type="JavaSDK"> | ||||||
|  |     <output url="file://$PROJECT_DIR$/build/classes" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="RunManager"> | ||||||
|  |     <configuration default="true" type="Remote" factoryName="Remote"> | ||||||
|  |       <option name="USE_SOCKET_TRANSPORT" value="true" /> | ||||||
|  |       <option name="SERVER_MODE" value="false" /> | ||||||
|  |       <option name="SHMEM_ADDRESS" value="javadebug" /> | ||||||
|  |       <option name="HOST" value="localhost" /> | ||||||
|  |       <option name="PORT" value="5005" /> | ||||||
|  |       <method /> | ||||||
|  |     </configuration> | ||||||
|  |     <configuration default="true" type="Applet" factoryName="Applet"> | ||||||
|  |       <module name="" /> | ||||||
|  |       <option name="MAIN_CLASS_NAME" /> | ||||||
|  |       <option name="HTML_FILE_NAME" /> | ||||||
|  |       <option name="HTML_USED" value="false" /> | ||||||
|  |       <option name="WIDTH" value="400" /> | ||||||
|  |       <option name="HEIGHT" value="300" /> | ||||||
|  |       <option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" /> | ||||||
|  |       <option name="VM_PARAMETERS" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH" /> | ||||||
|  |       <method /> | ||||||
|  |     </configuration> | ||||||
|  |     <configuration default="true" type="TestNG" factoryName="TestNG"> | ||||||
|  |       <module name="" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH" /> | ||||||
|  |       <option name="SUITE_NAME" /> | ||||||
|  |       <option name="PACKAGE_NAME" /> | ||||||
|  |       <option name="MAIN_CLASS_NAME" /> | ||||||
|  |       <option name="METHOD_NAME" /> | ||||||
|  |       <option name="GROUP_NAME" /> | ||||||
|  |       <option name="TEST_OBJECT" value="CLASS" /> | ||||||
|  |       <option name="VM_PARAMETERS" value="-ea" /> | ||||||
|  |       <option name="PARAMETERS" /> | ||||||
|  |       <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> | ||||||
|  |       <option name="OUTPUT_DIRECTORY" /> | ||||||
|  |       <option name="ANNOTATION_TYPE" /> | ||||||
|  |       <option name="ENV_VARIABLES" /> | ||||||
|  |       <option name="PASS_PARENT_ENVS" value="true" /> | ||||||
|  |       <option name="TEST_SEARCH_SCOPE"> | ||||||
|  |         <value defaultName="moduleWithDependencies" /> | ||||||
|  |       </option> | ||||||
|  |       <option name="USE_DEFAULT_REPORTERS" value="false" /> | ||||||
|  |       <option name="PROPERTIES_FILE" /> | ||||||
|  |       <envs /> | ||||||
|  |       <properties /> | ||||||
|  |       <listeners /> | ||||||
|  |       <method /> | ||||||
|  |     </configuration> | ||||||
|  |     <configuration default="true" type="Application" factoryName="Application"> | ||||||
|  |       <option name="MAIN_CLASS_NAME" /> | ||||||
|  |       <option name="VM_PARAMETERS" /> | ||||||
|  |       <option name="PROGRAM_PARAMETERS" /> | ||||||
|  |       <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH" /> | ||||||
|  |       <option name="ENABLE_SWING_INSPECTOR" value="false" /> | ||||||
|  |       <option name="ENV_VARIABLES" /> | ||||||
|  |       <option name="PASS_PARENT_ENVS" value="true" /> | ||||||
|  |       <module name="" /> | ||||||
|  |       <envs /> | ||||||
|  |       <method /> | ||||||
|  |     </configuration> | ||||||
|  |     <configuration default="true" type="JUnit" factoryName="JUnit"> | ||||||
|  |       <module name="" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> | ||||||
|  |       <option name="ALTERNATIVE_JRE_PATH" /> | ||||||
|  |       <option name="PACKAGE_NAME" /> | ||||||
|  |       <option name="MAIN_CLASS_NAME" /> | ||||||
|  |       <option name="METHOD_NAME" /> | ||||||
|  |       <option name="TEST_OBJECT" value="class" /> | ||||||
|  |       <option name="VM_PARAMETERS" value="-ea" /> | ||||||
|  |       <option name="PARAMETERS" /> | ||||||
|  |       <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> | ||||||
|  |       <option name="ENV_VARIABLES" /> | ||||||
|  |       <option name="PASS_PARENT_ENVS" value="true" /> | ||||||
|  |       <option name="TEST_SEARCH_SCOPE"> | ||||||
|  |         <value defaultName="moduleWithDependencies" /> | ||||||
|  |       </option> | ||||||
|  |       <envs /> | ||||||
|  |       <patterns /> | ||||||
|  |       <method /> | ||||||
|  |     </configuration> | ||||||
|  |     <list size="0" /> | ||||||
|  |     <configuration name="<template>" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" default="true" selected="false"> | ||||||
|  |       <option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" /> | ||||||
|  |     </configuration> | ||||||
|  |     <configuration name="<template>" type="WebApp" default="true" selected="false"> | ||||||
|  |       <Host>localhost</Host> | ||||||
|  |       <Port>5050</Port> | ||||||
|  |     </configuration> | ||||||
|  |   </component> | ||||||
|  |   <component name="masterDetails"> | ||||||
|  |     <states> | ||||||
|  |       <state key="ProjectJDKs.UI"> | ||||||
|  |         <settings> | ||||||
|  |           <last-edited>Android API 19 Platform</last-edited> | ||||||
|  |           <splitter-proportions> | ||||||
|  |             <option name="proportions"> | ||||||
|  |               <list> | ||||||
|  |                 <option value="0.2" /> | ||||||
|  |               </list> | ||||||
|  |             </option> | ||||||
|  |           </splitter-proportions> | ||||||
|  |         </settings> | ||||||
|  |       </state> | ||||||
|  |     </states> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
|  | 
 | ||||||
							
								
								
									
										11
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="ProjectModuleManager"> | ||||||
|  |     <modules> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/usb-serial-for-android.iml" filepath="$PROJECT_DIR$/usb-serial-for-android.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/usbSerialExamples/usbSerialExamples.iml" filepath="$PROJECT_DIR$/usbSerialExamples/usbSerialExamples.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/usbSerialForAndroid/usbSerialForAndroid.iml" filepath="$PROJECT_DIR$/usbSerialForAndroid/usbSerialForAndroid.iml" /> | ||||||
|  |     </modules> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
|  | 
 | ||||||
							
								
								
									
										5
									
								
								.idea/scopes/scope_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/scopes/scope_settings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | <component name="DependencyValidationManager"> | ||||||
|  |   <state> | ||||||
|  |     <option name="SKIP_IMPORT_STATEMENTS" value="false" /> | ||||||
|  |   </state> | ||||||
|  | </component> | ||||||
							
								
								
									
										7
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="VcsDirectoryMappings"> | ||||||
|  |     <mapping directory="" vcs="" /> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
|  | 
 | ||||||
							
								
								
									
										81
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								README.md
									
									
									
									
									
								
							| @ -15,13 +15,11 @@ functions for use with your own protocols. | |||||||
| 
 | 
 | ||||||
| ## Quick Start | ## Quick Start | ||||||
| 
 | 
 | ||||||
| **1.** Download [usb-serial-for-android-v010.jar](https://github.com/mik3y/usb-serial-for-android/releases/download/v0.1.0/usb-serial-for-android-v010.jar) | **1.** [Link your project](https://github.com/mik3y/usb-serial-for-android/wiki/Building-From-Source) to the library. | ||||||
| 
 | 
 | ||||||
| **2.** Copy the jar to your Android project's `libs/` directory. (See [Android's FAQ](http://developer.android.com/guide/faq/commontasks.html#addexternallibrary) for help). | **2.** Copy [device_filter.xml](http://usb-serial-for-android.googlecode.com/git/UsbSerialExamples/res/xml/device_filter.xml) to your project's `res/xml/` directory. | ||||||
| 
 | 
 | ||||||
| **3.** Copy [device_filter.xml](http://usb-serial-for-android.googlecode.com/git/UsbSerialExamples/res/xml/device_filter.xml) to your project's `res/xml/` directory. | **3.** Configure your `AndroidManifest.xml` to notify your app when a device is attached (see [Android USB Host documentation](http://developer.android.com/guide/topics/connectivity/usb/host.html#discovering-d) for help).   | ||||||
| 
 |  | ||||||
| **4.** Configure your `AndroidManifest.xml` to notify your app when a device is attached (see [Android USB Host documentation](http://developer.android.com/guide/topics/connectivity/usb/host.html#discovering-d) for help).   |  | ||||||
| 
 | 
 | ||||||
| ```xml | ```xml | ||||||
| <activity | <activity | ||||||
| @ -39,25 +37,33 @@ functions for use with your own protocols. | |||||||
| **5.** Use it! Example code snippet: | **5.** Use it! Example code snippet: | ||||||
| 
 | 
 | ||||||
| ```java | ```java | ||||||
| // Get UsbManager from Android. | // Find all available drivers from attached devices. | ||||||
| UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); | UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); | ||||||
|  | List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager); | ||||||
|  | if (availableDrivers.isEmpty()) { | ||||||
|  |   return; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // Find the first available driver. | // Open a connection to the first available driver. | ||||||
| UsbSerialDriver driver = UsbSerialProber.acquire(manager); | UsbSerialDriver driver = availableDrivers.get(0); | ||||||
|  | UsbDeviceConnection connection = manager.openDevice(driver.getDevice()); | ||||||
|  | if (connection == null) { | ||||||
|  |   // You probably need to call UsbManager.requestPermission(driver.getDevice(), ..) | ||||||
|  |   return; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| if (driver != null) { | // Read some data! Most have just one port (port 0). | ||||||
|   driver.open(); | UsbSerialPort port = driver.getPort(0); | ||||||
|   try { | port.open(connection); | ||||||
|     driver.setBaudRate(115200); | try { | ||||||
|      |   port.setBaudRate(115200); | ||||||
|     byte buffer[] = new byte[16]; |   byte buffer[] = new byte[16]; | ||||||
|     int numBytesRead = driver.read(buffer, 1000); |   int numBytesRead = port.read(buffer, 1000); | ||||||
|     Log.d(TAG, "Read " + numBytesRead + " bytes."); |   Log.d(TAG, "Read " + numBytesRead + " bytes."); | ||||||
|   } catch (IOException e) { | } catch (IOException e) { | ||||||
|     // Deal with error. |   // Deal with error. | ||||||
|   } finally { | } finally { | ||||||
|     driver.close(); |   port.close(); | ||||||
|   }  |  | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| @ -68,6 +74,39 @@ in git, which is a simple application for reading and showing serial data. | |||||||
| A [simple Arduino application](https://github.com/mik3y/usb-serial-for-android/blob/master/arduino) | A [simple Arduino application](https://github.com/mik3y/usb-serial-for-android/blob/master/arduino) | ||||||
| is also available which can be used for testing. | is also available which can be used for testing. | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | ## Probing for Unrecognized Devices | ||||||
|  | 
 | ||||||
|  | Sometimes you may need to do a little extra work to support devices which | ||||||
|  | usb-serial-for-android doesn't [yet] know about -- but which you know to be | ||||||
|  | compatible with one of the built-in drivers.  This may be the case for a brand | ||||||
|  | new device or for one using a custom VID/PID pair. | ||||||
|  | 
 | ||||||
|  | UsbSerialProber is a class to help you find and instantiate compatible | ||||||
|  | UsbSerialDrivers from the tree of connected UsbDevices.  Normally, you will use | ||||||
|  | the default prober returned by ``UsbSerialProber.getDefaultProber()``, which | ||||||
|  | uses the built-in list of well-known VIDs and PIDs that are supported by our | ||||||
|  | drivers. | ||||||
|  | 
 | ||||||
|  | To use your own set of rules, create and use a custom prober: | ||||||
|  | 
 | ||||||
|  | ```java | ||||||
|  | // Probe for our custom CDC devices, which use VID 0x1234 | ||||||
|  | // and PIDS 0x0001 and 0x0002. | ||||||
|  | ProbeTable customTable = new ProbeTable(); | ||||||
|  | probeTable.addProduct(0x1234, 0x0001, CdcAcmSerialDriver.class); | ||||||
|  | probeTable.addProduct(0x1234, 0x0002, CdcAcmSerialDriver.class); | ||||||
|  | 
 | ||||||
|  | UsbSerialProber prober = new UsbSerialProber(customTable); | ||||||
|  | List<UsbSerialDriver> drivers = prober.findAllDrivers(usbManager); | ||||||
|  | // ... | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Of course, nothing requires you to use UsbSerialProber at all: you can | ||||||
|  | instantiate driver classes directly if you know what you're doing; just supply | ||||||
|  | a compatible UsbDevice. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ## Compatible Devices | ## Compatible Devices | ||||||
| 
 | 
 | ||||||
| * *Serial chips:* FT232R, CDC/ACM (eg Arduino Uno) and possibly others. | * *Serial chips:* FT232R, CDC/ACM (eg Arduino Uno) and possibly others. | ||||||
|  | |||||||
| @ -1,10 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <classpath> |  | ||||||
| 	<classpathentry combineaccessrules="false" kind="src" path="/UsbSerialLibrary"/> |  | ||||||
| 	<classpathentry kind="src" path="src"/> |  | ||||||
| 	<classpathentry kind="src" path="gen"/> |  | ||||||
| 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> |  | ||||||
| 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> |  | ||||||
| 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> |  | ||||||
| 	<classpathentry kind="output" path="bin/classes"/> |  | ||||||
| </classpath> |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <projectDescription> |  | ||||||
| 	<name>UsbSerialExamples</name> |  | ||||||
| 	<comment></comment> |  | ||||||
| 	<projects> |  | ||||||
| 	</projects> |  | ||||||
| 	<buildSpec> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>org.eclipse.jdt.core.javabuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.ApkBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 	</buildSpec> |  | ||||||
| 	<natures> |  | ||||||
| 		<nature>com.android.ide.eclipse.adt.AndroidNature</nature> |  | ||||||
| 		<nature>org.eclipse.jdt.core.javanature</nature> |  | ||||||
| 	</natures> |  | ||||||
| </projectDescription> |  | ||||||
| @ -1,280 +0,0 @@ | |||||||
| #Thu Jun 02 12:32:09 PDT 2011 |  | ||||||
| eclipse.preferences.version=1 |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |  | ||||||
| org.eclipse.jdt.core.compiler.compliance=1.6 |  | ||||||
| org.eclipse.jdt.core.compiler.debug.lineNumber=generate |  | ||||||
| org.eclipse.jdt.core.compiler.debug.localVariable=generate |  | ||||||
| org.eclipse.jdt.core.compiler.debug.sourceFile=generate |  | ||||||
| org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |  | ||||||
| org.eclipse.jdt.core.compiler.source=1.6 |  | ||||||
| org.eclipse.jdt.core.formatter.align_type_members_on_columns=false |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_assignment=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_after_package=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_field=0 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_method=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_package=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_block_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_header=false |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_html=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_line_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_source_code=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.indent_root_tags=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert |  | ||||||
| org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.comment.line_length=80 |  | ||||||
| org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true |  | ||||||
| org.eclipse.jdt.core.formatter.compact_else_if=true |  | ||||||
| org.eclipse.jdt.core.formatter.continuation_indentation=2 |  | ||||||
| org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 |  | ||||||
| org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off |  | ||||||
| org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on |  | ||||||
| org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_empty_lines=false |  | ||||||
| org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true |  | ||||||
| org.eclipse.jdt.core.formatter.indentation.size=4 |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.join_lines_in_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.join_wrapped_lines=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.lineSplit=100 |  | ||||||
| org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false |  | ||||||
| org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false |  | ||||||
| org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 |  | ||||||
| org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 |  | ||||||
| org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true |  | ||||||
| org.eclipse.jdt.core.formatter.tabulation.char=space |  | ||||||
| org.eclipse.jdt.core.formatter.tabulation.size=4 |  | ||||||
| org.eclipse.jdt.core.formatter.use_on_off_tags=false |  | ||||||
| org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false |  | ||||||
| org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true |  | ||||||
| org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| eclipse.preferences.version=1 |  | ||||||
| formatter_profile=_Android |  | ||||||
| formatter_settings_version=11 |  | ||||||
| org.eclipse.jdt.ui.ignorelowercasenames=true |  | ||||||
| org.eclipse.jdt.ui.importorder=android;com;dalvik;gov;junit;libcore;net;org;java;javax; |  | ||||||
| org.eclipse.jdt.ui.ondemandthreshold=99 |  | ||||||
| org.eclipse.jdt.ui.staticondemandthreshold=99 |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| -optimizationpasses 5 |  | ||||||
| -dontusemixedcaseclassnames |  | ||||||
| -dontskipnonpubliclibraryclasses |  | ||||||
| -dontpreverify |  | ||||||
| -verbose |  | ||||||
| -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* |  | ||||||
| 
 |  | ||||||
| -keep public class * extends android.app.Activity |  | ||||||
| -keep public class * extends android.app.Application |  | ||||||
| -keep public class * extends android.app.Service |  | ||||||
| -keep public class * extends android.content.BroadcastReceiver |  | ||||||
| -keep public class * extends android.content.ContentProvider |  | ||||||
| -keep public class * extends android.app.backup.BackupAgentHelper |  | ||||||
| -keep public class * extends android.preference.Preference |  | ||||||
| -keep public class com.android.vending.licensing.ILicensingService |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembernames class * { |  | ||||||
|     native <methods>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembers class * { |  | ||||||
|     public <init>(android.content.Context, android.util.AttributeSet); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembers class * { |  | ||||||
|     public <init>(android.content.Context, android.util.AttributeSet, int); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclassmembers class * extends android.app.Activity { |  | ||||||
|    public void *(android.view.View); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclassmembers enum * { |  | ||||||
|     public static **[] values(); |  | ||||||
|     public static ** valueOf(java.lang.String); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keep class * implements android.os.Parcelable { |  | ||||||
|   public static final android.os.Parcelable$Creator *; |  | ||||||
| } |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| # This file is automatically generated by Android Tools. |  | ||||||
| # Do not modify this file -- YOUR CHANGES WILL BE ERASED! |  | ||||||
| # |  | ||||||
| # This file must be checked in Version Control Systems. |  | ||||||
| # |  | ||||||
| # To customize properties used by the Ant build system use, |  | ||||||
| # "ant.properties", and override values to adapt the script to your |  | ||||||
| # project structure. |  | ||||||
| 
 |  | ||||||
| # Project target. |  | ||||||
| target=android-12 |  | ||||||
| android.library.reference.1=../UsbSerialLibrary |  | ||||||
| @ -1,8 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <classpath> |  | ||||||
| 	<classpathentry kind="src" path="src"/> |  | ||||||
| 	<classpathentry kind="src" path="gen"/> |  | ||||||
| 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> |  | ||||||
| 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> |  | ||||||
| 	<classpathentry kind="output" path="bin/classes"/> |  | ||||||
| </classpath> |  | ||||||
| @ -1,33 +0,0 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <projectDescription> |  | ||||||
| 	<name>UsbSerialLibrary</name> |  | ||||||
| 	<comment></comment> |  | ||||||
| 	<projects> |  | ||||||
| 	</projects> |  | ||||||
| 	<buildSpec> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>org.eclipse.jdt.core.javabuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 		<buildCommand> |  | ||||||
| 			<name>com.android.ide.eclipse.adt.ApkBuilder</name> |  | ||||||
| 			<arguments> |  | ||||||
| 			</arguments> |  | ||||||
| 		</buildCommand> |  | ||||||
| 	</buildSpec> |  | ||||||
| 	<natures> |  | ||||||
| 		<nature>com.android.ide.eclipse.adt.AndroidNature</nature> |  | ||||||
| 		<nature>org.eclipse.jdt.core.javanature</nature> |  | ||||||
| 	</natures> |  | ||||||
| </projectDescription> |  | ||||||
| @ -1,349 +0,0 @@ | |||||||
| eclipse.preferences.version=1 |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 |  | ||||||
| org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |  | ||||||
| org.eclipse.jdt.core.compiler.compliance=1.6 |  | ||||||
| org.eclipse.jdt.core.compiler.debug.lineNumber=generate |  | ||||||
| org.eclipse.jdt.core.compiler.debug.localVariable=generate |  | ||||||
| org.eclipse.jdt.core.compiler.debug.sourceFile=generate |  | ||||||
| org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.autoboxing=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.comparingIdentical=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.deadCode=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.deprecation=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.discouragedReference=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.emptyStatement=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.fallthroughCase=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.fieldHiding=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.nullReference=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedImport=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedLabel=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning |  | ||||||
| org.eclipse.jdt.core.compiler.problem.unusedWarningToken=error |  | ||||||
| org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error |  | ||||||
| org.eclipse.jdt.core.compiler.source=1.6 |  | ||||||
| org.eclipse.jdt.core.formatter.align_type_members_on_columns=false |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_assignment=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_after_package=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_field=0 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_method=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_before_package=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 |  | ||||||
| org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line |  | ||||||
| org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_block_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_header=false |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_html=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_line_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.format_source_code=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.indent_root_tags=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert |  | ||||||
| org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.comment.line_length=80 |  | ||||||
| org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true |  | ||||||
| org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true |  | ||||||
| org.eclipse.jdt.core.formatter.compact_else_if=true |  | ||||||
| org.eclipse.jdt.core.formatter.continuation_indentation=2 |  | ||||||
| org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 |  | ||||||
| org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off |  | ||||||
| org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on |  | ||||||
| org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_empty_lines=false |  | ||||||
| org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true |  | ||||||
| org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true |  | ||||||
| org.eclipse.jdt.core.formatter.indentation.size=4 |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert |  | ||||||
| org.eclipse.jdt.core.formatter.join_lines_in_comments=true |  | ||||||
| org.eclipse.jdt.core.formatter.join_wrapped_lines=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false |  | ||||||
| org.eclipse.jdt.core.formatter.lineSplit=100 |  | ||||||
| org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false |  | ||||||
| org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false |  | ||||||
| org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 |  | ||||||
| org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 |  | ||||||
| org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true |  | ||||||
| org.eclipse.jdt.core.formatter.tabulation.char=space |  | ||||||
| org.eclipse.jdt.core.formatter.tabulation.size=4 |  | ||||||
| org.eclipse.jdt.core.formatter.use_on_off_tags=false |  | ||||||
| org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false |  | ||||||
| org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true |  | ||||||
| org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| eclipse.preferences.version=1 |  | ||||||
| formatter_profile=_Android |  | ||||||
| formatter_settings_version=11 |  | ||||||
| org.eclipse.jdt.ui.ignorelowercasenames=true |  | ||||||
| org.eclipse.jdt.ui.importorder=android;com;dalvik;gov;junit;libcore;net;org;java;javax; |  | ||||||
| org.eclipse.jdt.ui.ondemandthreshold=99 |  | ||||||
| org.eclipse.jdt.ui.staticondemandthreshold=99 |  | ||||||
| @ -1,36 +0,0 @@ | |||||||
| -optimizationpasses 5 |  | ||||||
| -dontusemixedcaseclassnames |  | ||||||
| -dontskipnonpubliclibraryclasses |  | ||||||
| -dontpreverify |  | ||||||
| -verbose |  | ||||||
| -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* |  | ||||||
| 
 |  | ||||||
| -keep public class * extends android.app.Activity |  | ||||||
| -keep public class * extends android.app.Application |  | ||||||
| -keep public class * extends android.app.Service |  | ||||||
| -keep public class * extends android.content.BroadcastReceiver |  | ||||||
| -keep public class * extends android.content.ContentProvider |  | ||||||
| -keep public class * extends android.app.backup.BackupAgentHelper |  | ||||||
| -keep public class * extends android.preference.Preference |  | ||||||
| -keep public class com.android.vending.licensing.ILicensingService |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembernames class * { |  | ||||||
|     native <methods>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembernames class * { |  | ||||||
|     public <init>(android.content.Context, android.util.AttributeSet); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclasseswithmembernames class * { |  | ||||||
|     public <init>(android.content.Context, android.util.AttributeSet, int); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keepclassmembers enum * { |  | ||||||
|     public static **[] values(); |  | ||||||
|     public static ** valueOf(java.lang.String); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| -keep class * implements android.os.Parcelable { |  | ||||||
|   public static final android.os.Parcelable$Creator *; |  | ||||||
| } |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| # This file is automatically generated by Android Tools. |  | ||||||
| # Do not modify this file -- YOUR CHANGES WILL BE ERASED! |  | ||||||
| # |  | ||||||
| # This file must be checked in Version Control Systems. |  | ||||||
| # |  | ||||||
| # To customize properties used by the Ant build system use, |  | ||||||
| # "ant.properties", and override values to adapt the script to your |  | ||||||
| # project structure. |  | ||||||
| 
 |  | ||||||
| # Project target. |  | ||||||
| target=android-12 |  | ||||||
| android.library=true |  | ||||||
| @ -1,248 +0,0 @@ | |||||||
| 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.util.Log; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.util.LinkedHashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * USB CDC/ACM serial driver implementation. |  | ||||||
|  * |  | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  | ||||||
|  * @see <a |  | ||||||
|  *      href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf">Universal |  | ||||||
|  *      Serial Bus Class Definitions for Communication Devices, v1.1</a> |  | ||||||
|  */ |  | ||||||
| public class CdcAcmSerialDriver extends CommonUsbSerialDriver { |  | ||||||
| 
 |  | ||||||
|     private final String TAG = CdcAcmSerialDriver.class.getSimpleName(); |  | ||||||
| 
 |  | ||||||
|     private UsbInterface mControlInterface; |  | ||||||
|     private UsbInterface mDataInterface; |  | ||||||
| 
 |  | ||||||
|     private UsbEndpoint mControlEndpoint; |  | ||||||
|     private UsbEndpoint mReadEndpoint; |  | ||||||
|     private UsbEndpoint mWriteEndpoint; |  | ||||||
| 
 |  | ||||||
|     private boolean mRts = false; |  | ||||||
|     private boolean mDtr = false; |  | ||||||
| 
 |  | ||||||
|     private static final int USB_RECIP_INTERFACE = 0x01; |  | ||||||
|     private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; |  | ||||||
| 
 |  | ||||||
|     private static final int SET_LINE_CODING = 0x20;  // USB CDC 1.1 section 6.2 |  | ||||||
|     private static final int GET_LINE_CODING = 0x21; |  | ||||||
|     private static final int SET_CONTROL_LINE_STATE = 0x22; |  | ||||||
|     private static final int SEND_BREAK = 0x23; |  | ||||||
| 
 |  | ||||||
|     public CdcAcmSerialDriver(UsbDevice device, UsbDeviceConnection connection) { |  | ||||||
|         super(device, connection); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void open() throws IOException { |  | ||||||
|         Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); |  | ||||||
| 
 |  | ||||||
|         Log.d(TAG, "Claiming control interface."); |  | ||||||
|         mControlInterface = mDevice.getInterface(0); |  | ||||||
|         Log.d(TAG, "Control iface=" + mControlInterface); |  | ||||||
|         // class should be USB_CLASS_COMM |  | ||||||
| 
 |  | ||||||
|         if (!mConnection.claimInterface(mControlInterface, true)) { |  | ||||||
|             throw new IOException("Could not claim control interface."); |  | ||||||
|         } |  | ||||||
|         mControlEndpoint = mControlInterface.getEndpoint(0); |  | ||||||
|         Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection()); |  | ||||||
| 
 |  | ||||||
|         Log.d(TAG, "Claiming data interface."); |  | ||||||
|         mDataInterface = mDevice.getInterface(1); |  | ||||||
|         Log.d(TAG, "data iface=" + mDataInterface); |  | ||||||
|         // class should be USB_CLASS_CDC_DATA |  | ||||||
| 
 |  | ||||||
|         if (!mConnection.claimInterface(mDataInterface, true)) { |  | ||||||
|             throw new IOException("Could not claim data interface."); |  | ||||||
|         } |  | ||||||
|         mReadEndpoint = mDataInterface.getEndpoint(1); |  | ||||||
|         Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection()); |  | ||||||
|         mWriteEndpoint = mDataInterface.getEndpoint(0); |  | ||||||
|         Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private int sendAcmControlMessage(int request, int value, byte[] buf) { |  | ||||||
|         return mConnection.controlTransfer( |  | ||||||
|                 USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void close() throws IOException { |  | ||||||
|         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 { |  | ||||||
|         // TODO(mikey): Nearly identical to FtdiSerial write. Refactor. |  | ||||||
|         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 |  | ||||||
|     public void setParameters(int baudRate, int dataBits, int stopBits, int parity) { |  | ||||||
|         byte stopBitsByte; |  | ||||||
|         switch (stopBits) { |  | ||||||
|             case STOPBITS_1: stopBitsByte = 0; break; |  | ||||||
|             case STOPBITS_1_5: stopBitsByte = 1; break; |  | ||||||
|             case STOPBITS_2: stopBitsByte = 2; break; |  | ||||||
|             default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         byte parityBitesByte; |  | ||||||
|         switch (parity) { |  | ||||||
|             case PARITY_NONE: parityBitesByte = 0; break; |  | ||||||
|             case PARITY_ODD: parityBitesByte = 1; break; |  | ||||||
|             case PARITY_EVEN: parityBitesByte = 2; break; |  | ||||||
|             case PARITY_MARK: parityBitesByte = 3; break; |  | ||||||
|             case PARITY_SPACE: parityBitesByte = 4; break; |  | ||||||
|             default: throw new IllegalArgumentException("Bad value for parity: " + parity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         byte[] msg = { |  | ||||||
|                 (byte) ( baudRate & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 8 ) & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 16) & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 24) & 0xff), |  | ||||||
|                 stopBitsByte, |  | ||||||
|                 parityBitesByte, |  | ||||||
|                 (byte) dataBits}; |  | ||||||
|         sendAcmControlMessage(SET_LINE_CODING, 0, msg); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getCD() throws IOException { |  | ||||||
|         return false;  // TODO |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getCTS() throws IOException { |  | ||||||
|         return false;  // TODO |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getDSR() throws IOException { |  | ||||||
|         return false;  // TODO |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getDTR() throws IOException { |  | ||||||
|         return mDtr; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setDTR(boolean value) throws IOException { |  | ||||||
|         mDtr = value; |  | ||||||
|         setDtrRts(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRI() throws IOException { |  | ||||||
|         return false;  // TODO |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRTS() throws IOException { |  | ||||||
|         return mRts; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setRTS(boolean value) throws IOException { |  | ||||||
|         mRts = value; |  | ||||||
|         setDtrRts(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void setDtrRts() { |  | ||||||
|         int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0); |  | ||||||
|         sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static Map<Integer, int[]> getSupportedDevices() { |  | ||||||
|         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO), |  | ||||||
|                 new int[] { |  | ||||||
|                         UsbId.ARDUINO_UNO, |  | ||||||
|                         UsbId.ARDUINO_UNO_R3, |  | ||||||
|                         UsbId.ARDUINO_MEGA_2560, |  | ||||||
|                         UsbId.ARDUINO_MEGA_2560_R3, |  | ||||||
|                         UsbId.ARDUINO_SERIAL_ADAPTER, |  | ||||||
|                         UsbId.ARDUINO_SERIAL_ADAPTER_R3, |  | ||||||
|                         UsbId.ARDUINO_MEGA_ADK, |  | ||||||
|                         UsbId.ARDUINO_MEGA_ADK_R3, |  | ||||||
|                         UsbId.ARDUINO_LEONARDO, |  | ||||||
|                 }); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH), |  | ||||||
|                 new int[] { |  | ||||||
|                     UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL, |  | ||||||
|                 }); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ATMEL), |  | ||||||
|                 new int[] { |  | ||||||
|                     UsbId.ATMEL_LUFA_CDC_DEMO_APP, |  | ||||||
|                 }); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_LEAFLABS), |  | ||||||
|                 new int[] { |  | ||||||
|                     UsbId.LEAFLABS_MAPLE, |  | ||||||
|                 }); |  | ||||||
|         return supportedDevices; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,291 +0,0 @@ | |||||||
| 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 CommonUsbSerialDriver { |  | ||||||
|     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; |  | ||||||
|     private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12; |  | ||||||
|      |  | ||||||
|     private static final int FLUSH_READ_CODE = 0x0a; |  | ||||||
|     private static final int FLUSH_WRITE_CODE = 0x05; |  | ||||||
|      |  | ||||||
|     /* |  | ||||||
|      * 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void setBaudRate(int baudRate) throws IOException {    |  | ||||||
|         byte[] data = new byte[] { |  | ||||||
|                 (byte) ( baudRate & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 8 ) & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 16) & 0xff), |  | ||||||
|                 (byte) ((baudRate >> 24) & 0xff) |  | ||||||
|         }; |  | ||||||
|         int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,  |  | ||||||
|                 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|         if (ret < 0) { |  | ||||||
|             throw new IOException("Error setting baud rate."); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @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 boolean purgeHwBuffers(boolean purgeReadBuffers, |  | ||||||
|             boolean purgeWriteBuffers) throws IOException { |  | ||||||
|         int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0) |  | ||||||
|                 | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0); |  | ||||||
| 
 |  | ||||||
|         if (value != 0) { |  | ||||||
|             setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,548 +0,0 @@ | |||||||
| /* 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.UsbRequest; |  | ||||||
| import android.util.Log; |  | ||||||
| 
 |  | ||||||
| import com.hoho.android.usbserial.util.HexDump; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.nio.ByteBuffer; |  | ||||||
| import java.util.LinkedHashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * A {@link CommonUsbSerialDriver} implementation for a variety of FTDI devices |  | ||||||
|  * <p> |  | ||||||
|  * This driver is based on |  | ||||||
|  * <a href="http://www.intra2net.com/en/developer/libftdi">libftdi</a>, and is |  | ||||||
|  * copyright and subject to the following terms: |  | ||||||
|  * |  | ||||||
|  * <pre> |  | ||||||
|  *   Copyright (C) 2003 by Intra2net AG |  | ||||||
|  * |  | ||||||
|  *   This program is free software; you can redistribute it and/or modify |  | ||||||
|  *   it under the terms of the GNU Lesser General Public License |  | ||||||
|  *   version 2.1 as published by the Free Software Foundation; |  | ||||||
|  * |  | ||||||
|  *   opensource@intra2net.com |  | ||||||
|  *   http://www.intra2net.com/en/developer/libftdi |  | ||||||
|  * </pre> |  | ||||||
|  * |  | ||||||
|  * </p> |  | ||||||
|  * <p> |  | ||||||
|  * Some FTDI devices have not been tested; see later listing of supported and |  | ||||||
|  * unsupported devices. Devices listed as "supported" support the following |  | ||||||
|  * features: |  | ||||||
|  * <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> |  | ||||||
|  * <p> |  | ||||||
|  * Supported and tested devices: |  | ||||||
|  * <ul> |  | ||||||
|  * <li>{@value DeviceType#TYPE_R}</li> |  | ||||||
|  * </ul> |  | ||||||
|  * </p> |  | ||||||
|  * <p> |  | ||||||
|  * Unsupported but possibly working devices (please contact the author with |  | ||||||
|  * 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> |  | ||||||
|  * </p> |  | ||||||
|  * |  | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  | ||||||
|  * @see <a href="http://code.google.com/p/usb-serial-for-android/">USB Serial |  | ||||||
|  * for Android project page</a> |  | ||||||
|  * @see <a href="http://www.ftdichip.com/">FTDI Homepage</a> |  | ||||||
|  * @see <a href="http://www.intra2net.com/en/developer/libftdi">libftdi</a> |  | ||||||
|  */ |  | ||||||
| public class FtdiSerialDriver extends CommonUsbSerialDriver { |  | ||||||
| 
 |  | ||||||
|     public static final int USB_TYPE_STANDARD = 0x00 << 5; |  | ||||||
|     public static final int USB_TYPE_CLASS = 0x01 << 5; |  | ||||||
|     public static final int USB_TYPE_VENDOR = 0x02 << 5; |  | ||||||
|     public static final int USB_TYPE_RESERVED = 0x03 << 5; |  | ||||||
| 
 |  | ||||||
|     public static final int USB_RECIP_DEVICE = 0x00; |  | ||||||
|     public static final int USB_RECIP_INTERFACE = 0x01; |  | ||||||
|     public static final int USB_RECIP_ENDPOINT = 0x02; |  | ||||||
|     public static final int USB_RECIP_OTHER = 0x03; |  | ||||||
| 
 |  | ||||||
|     public static final int USB_ENDPOINT_IN = 0x80; |  | ||||||
|     public static final int USB_ENDPOINT_OUT = 0x00; |  | ||||||
| 
 |  | ||||||
|     public static final int USB_WRITE_TIMEOUT_MILLIS = 5000; |  | ||||||
|     public static final int USB_READ_TIMEOUT_MILLIS = 5000; |  | ||||||
| 
 |  | ||||||
|     // From ftdi.h |  | ||||||
|     /** |  | ||||||
|      * Reset the port. |  | ||||||
|      */ |  | ||||||
|     private static final int SIO_RESET_REQUEST = 0; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set the modem control register. |  | ||||||
|      */ |  | ||||||
|     private static final int SIO_MODEM_CTRL_REQUEST = 1; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set flow control register. |  | ||||||
|      */ |  | ||||||
|     private static final int SIO_SET_FLOW_CTRL_REQUEST = 2; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set baud rate. |  | ||||||
|      */ |  | ||||||
|     private static final int SIO_SET_BAUD_RATE_REQUEST = 3; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Set the data characteristics of the port. |  | ||||||
|      */ |  | ||||||
|     private static final int SIO_SET_DATA_REQUEST = 4; |  | ||||||
| 
 |  | ||||||
|     private static final int SIO_RESET_SIO = 0; |  | ||||||
|     private static final int SIO_RESET_PURGE_RX = 1; |  | ||||||
|     private static final int SIO_RESET_PURGE_TX = 2; |  | ||||||
| 
 |  | ||||||
|     public static final int FTDI_DEVICE_OUT_REQTYPE = |  | ||||||
|             UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT; |  | ||||||
| 
 |  | ||||||
|     public static final int FTDI_DEVICE_IN_REQTYPE = |  | ||||||
|             UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Length of the modem status header, transmitted with every read. |  | ||||||
|      */ |  | ||||||
|     private static final int MODEM_STATUS_HEADER_LENGTH = 2; |  | ||||||
| 
 |  | ||||||
|     private final String TAG = FtdiSerialDriver.class.getSimpleName(); |  | ||||||
| 
 |  | ||||||
|     private DeviceType mType; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * FTDI chip types. |  | ||||||
|      */ |  | ||||||
|     private static enum DeviceType { |  | ||||||
|         TYPE_BM, TYPE_AM, TYPE_2232C, TYPE_R, TYPE_2232H, TYPE_4232H; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private int mInterface = 0; /* INTERFACE_ANY */ |  | ||||||
| 
 |  | ||||||
|     private int mMaxPacketSize = 64; // TODO(mikey): detect |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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. |  | ||||||
|      */ |  | ||||||
|     private static final boolean ENABLE_ASYNC_READS = false; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Filter FTDI status bytes from buffer |  | ||||||
|      * @param src The source buffer (which contains status bytes) |  | ||||||
|      * @param dest The destination buffer to write the status bytes into (can be src) |  | ||||||
|      * @param totalBytesRead Number of bytes read to src |  | ||||||
|      * @param maxPacketSize The USB endpoint max packet size |  | ||||||
|      * @return The number of payload bytes |  | ||||||
|      */ |  | ||||||
|     private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) { |  | ||||||
|         final int packetsCount = totalBytesRead / maxPacketSize + 1; |  | ||||||
|         for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) { |  | ||||||
|             final int count = (packetIdx == (packetsCount - 1)) |  | ||||||
|                     ? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH |  | ||||||
|                     : maxPacketSize - MODEM_STATUS_HEADER_LENGTH; |  | ||||||
|             if (count > 0) { |  | ||||||
|                 System.arraycopy(src, |  | ||||||
|                         packetIdx * maxPacketSize + MODEM_STATUS_HEADER_LENGTH, |  | ||||||
|                         dest, |  | ||||||
|                         packetIdx * (maxPacketSize - MODEM_STATUS_HEADER_LENGTH), |  | ||||||
|                         count); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|       return totalBytesRead - (packetsCount * 2); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * 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 FtdiSerialDriver(UsbDevice usbDevice, UsbDeviceConnection usbConnection) { |  | ||||||
|         super(usbDevice, usbConnection); |  | ||||||
|         mType = null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void reset() throws IOException { |  | ||||||
|         int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, |  | ||||||
|                 SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|         if (result != 0) { |  | ||||||
|             throw new IOException("Reset failed: result=" + result); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // TODO(mikey): autodetect. |  | ||||||
|         mType = DeviceType.TYPE_R; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @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 { |  | ||||||
|                     throw new IOException("Error claiming interface " + i); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             reset(); |  | ||||||
|             opened = true; |  | ||||||
|         } finally { |  | ||||||
|             if (!opened) { |  | ||||||
|                 close(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void close() { |  | ||||||
|         mConnection.close(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public int read(byte[] dest, int timeoutMillis) throws IOException { |  | ||||||
|         final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0); |  | ||||||
| 
 |  | ||||||
|         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, endpoint); |  | ||||||
| 
 |  | ||||||
|             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 payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH; |  | ||||||
|             if (payloadBytesRead > 0) { |  | ||||||
|                 Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length))); |  | ||||||
|                 return payloadBytesRead; |  | ||||||
|             } else { |  | ||||||
|                 return 0; |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             final int totalBytesRead; |  | ||||||
| 
 |  | ||||||
|             synchronized (mReadBufferLock) { |  | ||||||
|                 final int readAmt = Math.min(dest.length, mReadBuffer.length); |  | ||||||
|                 totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer, |  | ||||||
|                         readAmt, timeoutMillis); |  | ||||||
| 
 |  | ||||||
|                 if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) { |  | ||||||
|                     throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes"); |  | ||||||
|                 } |  | ||||||
|    |  | ||||||
|                 return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize()); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public int write(byte[] src, int timeoutMillis) throws IOException { |  | ||||||
|         final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1); |  | ||||||
|         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(endpoint, 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; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private int setBaudRate(int baudRate) throws IOException { |  | ||||||
|         long[] vals = convertBaudrate(baudRate); |  | ||||||
|         long actualBaudrate = vals[0]; |  | ||||||
|         long index = vals[1]; |  | ||||||
|         long value = vals[2]; |  | ||||||
|         int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, |  | ||||||
|                 SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index, |  | ||||||
|                 null, 0, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|         if (result != 0) { |  | ||||||
|             throw new IOException("Setting baudrate failed: result=" + result); |  | ||||||
|         } |  | ||||||
|         return (int) actualBaudrate; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setParameters(int baudRate, int dataBits, int stopBits, int parity) |  | ||||||
|             throws IOException { |  | ||||||
|         setBaudRate(baudRate); |  | ||||||
| 
 |  | ||||||
|         int config = dataBits; |  | ||||||
| 
 |  | ||||||
|         switch (parity) { |  | ||||||
|             case PARITY_NONE: |  | ||||||
|                 config |= (0x00 << 8); |  | ||||||
|                 break; |  | ||||||
|             case PARITY_ODD: |  | ||||||
|                 config |= (0x01 << 8); |  | ||||||
|                 break; |  | ||||||
|             case PARITY_EVEN: |  | ||||||
|                 config |= (0x02 << 8); |  | ||||||
|                 break; |  | ||||||
|             case PARITY_MARK: |  | ||||||
|                 config |= (0x03 << 8); |  | ||||||
|                 break; |  | ||||||
|             case PARITY_SPACE: |  | ||||||
|                 config |= (0x04 << 8); |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 throw new IllegalArgumentException("Unknown parity value: " + parity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         switch (stopBits) { |  | ||||||
|             case STOPBITS_1: |  | ||||||
|                 config |= (0x00 << 11); |  | ||||||
|                 break; |  | ||||||
|             case STOPBITS_1_5: |  | ||||||
|                 config |= (0x01 << 11); |  | ||||||
|                 break; |  | ||||||
|             case STOPBITS_2: |  | ||||||
|                 config |= (0x02 << 11); |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, |  | ||||||
|                 SIO_SET_DATA_REQUEST, config, 0 /* index */, |  | ||||||
|                 null, 0, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|         if (result != 0) { |  | ||||||
|             throw new IOException("Setting parameters failed: result=" + result); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private long[] convertBaudrate(int baudrate) { |  | ||||||
|         // TODO(mikey): Braindead transcription of libfti method.  Clean up, |  | ||||||
|         // using more idiomatic Java where possible. |  | ||||||
|         int divisor = 24000000 / baudrate; |  | ||||||
|         int bestDivisor = 0; |  | ||||||
|         int bestBaud = 0; |  | ||||||
|         int bestBaudDiff = 0; |  | ||||||
|         int fracCode[] = { |  | ||||||
|                 0, 3, 2, 4, 1, 5, 6, 7 |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         for (int i = 0; i < 2; i++) { |  | ||||||
|             int tryDivisor = divisor + i; |  | ||||||
|             int baudEstimate; |  | ||||||
|             int baudDiff; |  | ||||||
| 
 |  | ||||||
|             if (tryDivisor <= 8) { |  | ||||||
|                 // Round up to minimum supported divisor |  | ||||||
|                 tryDivisor = 8; |  | ||||||
|             } else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) { |  | ||||||
|                 // BM doesn't support divisors 9 through 11 inclusive |  | ||||||
|                 tryDivisor = 12; |  | ||||||
|             } else if (divisor < 16) { |  | ||||||
|                 // AM doesn't support divisors 9 through 15 inclusive |  | ||||||
|                 tryDivisor = 16; |  | ||||||
|             } else { |  | ||||||
|                 if (mType == DeviceType.TYPE_AM) { |  | ||||||
|                     // TODO |  | ||||||
|                 } else { |  | ||||||
|                     if (tryDivisor > 0x1FFFF) { |  | ||||||
|                         // Round down to maximum supported divisor value (for |  | ||||||
|                         // BM) |  | ||||||
|                         tryDivisor = 0x1FFFF; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // Get estimated baud rate (to nearest integer) |  | ||||||
|             baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor; |  | ||||||
| 
 |  | ||||||
|             // Get absolute difference from requested baud rate |  | ||||||
|             if (baudEstimate < baudrate) { |  | ||||||
|                 baudDiff = baudrate - baudEstimate; |  | ||||||
|             } else { |  | ||||||
|                 baudDiff = baudEstimate - baudrate; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (i == 0 || baudDiff < bestBaudDiff) { |  | ||||||
|                 // Closest to requested baud rate so far |  | ||||||
|                 bestDivisor = tryDivisor; |  | ||||||
|                 bestBaud = baudEstimate; |  | ||||||
|                 bestBaudDiff = baudDiff; |  | ||||||
|                 if (baudDiff == 0) { |  | ||||||
|                     // Spot on! No point trying |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Encode the best divisor value |  | ||||||
|         long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14); |  | ||||||
|         // Deal with special cases for encoded value |  | ||||||
|         if (encodedDivisor == 1) { |  | ||||||
|             encodedDivisor = 0; // 3000000 baud |  | ||||||
|         } else if (encodedDivisor == 0x4001) { |  | ||||||
|             encodedDivisor = 1; // 2000000 baud (BM only) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Split into "value" and "index" values |  | ||||||
|         long value = encodedDivisor & 0xFFFF; |  | ||||||
|         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 */; |  | ||||||
|         } else { |  | ||||||
|             index = (encodedDivisor >> 16) & 0xffff; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Return the nearest baud rate |  | ||||||
|         return new long[] { |  | ||||||
|                 bestBaud, index, value |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @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 false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setDTR(boolean value) throws IOException { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRI() throws IOException { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRTS() throws IOException { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setRTS(boolean value) throws IOException { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     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); |  | ||||||
|             if (result != 0) { |  | ||||||
|                 throw new IOException("Flushing RX failed: result=" + result); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         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); |  | ||||||
|             if (result != 0) { |  | ||||||
|                 throw new IOException("Flushing RX failed: result=" + result); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static Map<Integer, int[]> getSupportedDevices() { |  | ||||||
|         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI), |  | ||||||
|                 new int[] { |  | ||||||
|                     UsbId.FTDI_FT232R, |  | ||||||
|                     UsbId.FTDI_FT231X,                     |  | ||||||
|                 }); |  | ||||||
|         return supportedDevices; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,522 +0,0 @@ | |||||||
| /* 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/ |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
|  * Ported to usb-serial-for-android |  | ||||||
|  * by Felix Hädicke <felixhaedicke@web.de> |  | ||||||
|  * |  | ||||||
|  * Based on the pyprolific driver written |  | ||||||
|  * by Emmanuel Blot <emmanuel.blot@free.fr> |  | ||||||
|  * See https://github.com/eblot/pyftdi |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| 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.util.Log; |  | ||||||
| 
 |  | ||||||
| import java.io.IOException; |  | ||||||
| import java.lang.reflect.Method; |  | ||||||
| import java.util.LinkedHashMap; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| public class ProlificSerialDriver extends CommonUsbSerialDriver { |  | ||||||
|     private static final int USB_READ_TIMEOUT_MILLIS = 1000; |  | ||||||
|     private static final int USB_WRITE_TIMEOUT_MILLIS = 5000; |  | ||||||
| 
 |  | ||||||
|     private static final int USB_RECIP_INTERFACE = 0x01; |  | ||||||
| 
 |  | ||||||
|     private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01; |  | ||||||
|     private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01; |  | ||||||
| 
 |  | ||||||
|     private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT |  | ||||||
|             | UsbConstants.USB_TYPE_VENDOR; |  | ||||||
| 
 |  | ||||||
|     private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN |  | ||||||
|             | UsbConstants.USB_TYPE_VENDOR; |  | ||||||
| 
 |  | ||||||
|     private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT |  | ||||||
|             | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; |  | ||||||
| 
 |  | ||||||
|     private static final int WRITE_ENDPOINT = 0x02; |  | ||||||
|     private static final int READ_ENDPOINT = 0x83; |  | ||||||
|     private static final int INTERRUPT_ENDPOINT = 0x81; |  | ||||||
| 
 |  | ||||||
|     private static final int FLUSH_RX_REQUEST = 0x08; |  | ||||||
|     private static final int FLUSH_TX_REQUEST = 0x09; |  | ||||||
| 
 |  | ||||||
|     private static final int SET_LINE_REQUEST = 0x20; |  | ||||||
|     private static final int SET_CONTROL_REQUEST = 0x22; |  | ||||||
| 
 |  | ||||||
|     private static final int CONTROL_DTR = 0x01; |  | ||||||
|     private static final int CONTROL_RTS = 0x02; |  | ||||||
| 
 |  | ||||||
|     private static final int STATUS_FLAG_CD = 0x01; |  | ||||||
|     private static final int STATUS_FLAG_DSR = 0x02; |  | ||||||
|     private static final int STATUS_FLAG_RI = 0x08; |  | ||||||
|     private static final int STATUS_FLAG_CTS = 0x80; |  | ||||||
| 
 |  | ||||||
|     private static final int STATUS_BUFFER_SIZE = 10; |  | ||||||
|     private static final int STATUS_BYTE_IDX = 8; |  | ||||||
| 
 |  | ||||||
|     private static final int DEVICE_TYPE_HX = 0; |  | ||||||
|     private static final int DEVICE_TYPE_0 = 1; |  | ||||||
|     private static final int DEVICE_TYPE_1 = 2; |  | ||||||
| 
 |  | ||||||
|     private int mDeviceType = DEVICE_TYPE_HX; |  | ||||||
| 
 |  | ||||||
|     private UsbEndpoint mReadEndpoint; |  | ||||||
|     private UsbEndpoint mWriteEndpoint; |  | ||||||
|     private UsbEndpoint mInterruptEndpoint; |  | ||||||
| 
 |  | ||||||
|     private int mControlLinesValue = 0; |  | ||||||
| 
 |  | ||||||
|     private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1; |  | ||||||
| 
 |  | ||||||
|     private int mStatus = 0; |  | ||||||
|     private volatile Thread mReadStatusThread = null; |  | ||||||
|     private final Object mReadStatusThreadLock = new Object(); |  | ||||||
|     boolean mStopReadStatusThread = false; |  | ||||||
|     private IOException mReadStatusException = null; |  | ||||||
| 
 |  | ||||||
|     private final String TAG = ProlificSerialDriver.class.getSimpleName(); |  | ||||||
| 
 |  | ||||||
|     private final byte[] inControlTransfer(int requestType, int request, |  | ||||||
|             int value, int index, int length) throws IOException { |  | ||||||
|         byte[] buffer = new byte[length]; |  | ||||||
|         int result = mConnection.controlTransfer(requestType, request, value, |  | ||||||
|                 index, buffer, length, USB_READ_TIMEOUT_MILLIS); |  | ||||||
|         if (result != length) { |  | ||||||
|             throw new IOException( |  | ||||||
|                     String.format("ControlTransfer with value 0x%x failed: %d", |  | ||||||
|                             value, result)); |  | ||||||
|         } |  | ||||||
|         return buffer; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final void outControlTransfer(int requestType, int request, |  | ||||||
|             int value, int index, byte[] data) throws IOException { |  | ||||||
|         int length = (data == null) ? 0 : data.length; |  | ||||||
|         int result = mConnection.controlTransfer(requestType, request, value, |  | ||||||
|                 index, data, length, USB_WRITE_TIMEOUT_MILLIS); |  | ||||||
|         if (result != length) { |  | ||||||
|             throw new IOException( |  | ||||||
|                     String.format("ControlTransfer with value 0x%x failed: %d", |  | ||||||
|                             value, result)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final byte[] vendorIn(int value, int index, int length) |  | ||||||
|             throws IOException { |  | ||||||
|         return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, |  | ||||||
|                 PROLIFIC_VENDOR_READ_REQUEST, value, index, length); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final void vendorOut(int value, int index, byte[] data) |  | ||||||
|             throws IOException { |  | ||||||
|         outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, |  | ||||||
|                 PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final void ctrlOut(int request, int value, int index, byte[] data) |  | ||||||
|             throws IOException { |  | ||||||
|         outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, |  | ||||||
|                 data); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void doBlackMagic() throws IOException { |  | ||||||
|         vendorIn(0x8484, 0, 1); |  | ||||||
|         vendorOut(0x0404, 0, null); |  | ||||||
|         vendorIn(0x8484, 0, 1); |  | ||||||
|         vendorIn(0x8383, 0, 1); |  | ||||||
|         vendorIn(0x8484, 0, 1); |  | ||||||
|         vendorOut(0x0404, 1, null); |  | ||||||
|         vendorIn(0x8484, 0, 1); |  | ||||||
|         vendorIn(0x8383, 0, 1); |  | ||||||
|         vendorOut(0, 1, null); |  | ||||||
|         vendorOut(1, 0, null); |  | ||||||
|         vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void resetDevice() throws IOException { |  | ||||||
|         purgeHwBuffers(true, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void setControlLines(int newControlLinesValue) throws IOException { |  | ||||||
|         ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null); |  | ||||||
|         mControlLinesValue = newControlLinesValue; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final void readStatusThreadFunction() { |  | ||||||
|         try { |  | ||||||
|             while (!mStopReadStatusThread) { |  | ||||||
|                 byte[] buffer = new byte[STATUS_BUFFER_SIZE]; |  | ||||||
|                 int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint, |  | ||||||
|                         buffer, |  | ||||||
|                         STATUS_BUFFER_SIZE, |  | ||||||
|                         500); |  | ||||||
|                 if (readBytesCount > 0) { |  | ||||||
|                     if (readBytesCount == STATUS_BUFFER_SIZE) { |  | ||||||
|                         mStatus = buffer[STATUS_BYTE_IDX] & 0xff; |  | ||||||
|                     } else { |  | ||||||
|                         throw new IOException( |  | ||||||
|                                 String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d", |  | ||||||
|                                         STATUS_BUFFER_SIZE, |  | ||||||
|                                         readBytesCount)); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } catch (IOException e) { |  | ||||||
|             mReadStatusException = e; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final int getStatus() throws IOException { |  | ||||||
|         if ((mReadStatusThread == null) && (mReadStatusException == null)) { |  | ||||||
|             synchronized (mReadStatusThreadLock) { |  | ||||||
|                 if (mReadStatusThread == null) { |  | ||||||
|                     byte[] buffer = new byte[STATUS_BUFFER_SIZE]; |  | ||||||
|                     int readBytes = mConnection.bulkTransfer(mInterruptEndpoint, |  | ||||||
|                             buffer, |  | ||||||
|                             STATUS_BUFFER_SIZE, |  | ||||||
|                             100); |  | ||||||
|                     if (readBytes != STATUS_BUFFER_SIZE) { |  | ||||||
|                         Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status"); |  | ||||||
|                     } else { |  | ||||||
|                         mStatus = buffer[STATUS_BYTE_IDX] & 0xff; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     mReadStatusThread = new Thread(new Runnable() { |  | ||||||
|                         @Override |  | ||||||
|                         public void run() { |  | ||||||
|                             readStatusThreadFunction(); |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|                     mReadStatusThread.setDaemon(true); |  | ||||||
|                     mReadStatusThread.start(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /* throw and clear an exception which occured in the status read thread */ |  | ||||||
|         IOException readStatusException = mReadStatusException; |  | ||||||
|         if (mReadStatusException != null) { |  | ||||||
|             mReadStatusException = null; |  | ||||||
|             throw readStatusException; |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         return mStatus; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private final boolean testStatusFlag(int flag) throws IOException { |  | ||||||
|         return ((getStatus() & flag) == flag); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public ProlificSerialDriver(UsbDevice device, UsbDeviceConnection connection) { |  | ||||||
|         super(device, connection); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void open() throws IOException { |  | ||||||
|         UsbInterface usbInterface = mDevice.getInterface(0); |  | ||||||
| 
 |  | ||||||
|         if (!mConnection.claimInterface(usbInterface, true)) { |  | ||||||
|             throw new IOException("Error claiming Prolific interface 0"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         boolean openSuccessful = false; |  | ||||||
|         try { |  | ||||||
|             for (int i = 0; i < usbInterface.getEndpointCount(); ++i) { |  | ||||||
|                 UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i); |  | ||||||
| 
 |  | ||||||
|                 switch (currentEndpoint.getAddress()) { |  | ||||||
|                 case READ_ENDPOINT: |  | ||||||
|                     mReadEndpoint = currentEndpoint; |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 case WRITE_ENDPOINT: |  | ||||||
|                     mWriteEndpoint = currentEndpoint; |  | ||||||
|                     break; |  | ||||||
| 
 |  | ||||||
|                 case INTERRUPT_ENDPOINT: |  | ||||||
|                     mInterruptEndpoint = currentEndpoint; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (mDevice.getDeviceClass() == 0x02) { |  | ||||||
|                 mDeviceType = DEVICE_TYPE_0; |  | ||||||
|             } else { |  | ||||||
|                 try { |  | ||||||
|                     Method getRawDescriptorsMethod |  | ||||||
|                         = mConnection.getClass().getMethod("getRawDescriptors"); |  | ||||||
|                     byte[] rawDescriptors |  | ||||||
|                         = (byte[]) getRawDescriptorsMethod.invoke(mConnection); |  | ||||||
|                     byte maxPacketSize0 = rawDescriptors[7]; |  | ||||||
|                     if (maxPacketSize0 == 64) { |  | ||||||
|                         mDeviceType = DEVICE_TYPE_HX; |  | ||||||
|                     } else if ((mDevice.getDeviceClass() == 0x00) |  | ||||||
|                             || (mDevice.getDeviceClass() == 0xff)) { |  | ||||||
|                         mDeviceType = DEVICE_TYPE_1; |  | ||||||
|                     } else { |  | ||||||
|                       Log.w(TAG, "Could not detect PL2303 subtype, " |  | ||||||
|                           + "Assuming that it is a HX device"); |  | ||||||
|                       mDeviceType = DEVICE_TYPE_HX; |  | ||||||
|                     } |  | ||||||
|                 } catch (NoSuchMethodException e) { |  | ||||||
|                     Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, " |  | ||||||
|                             + "required for PL2303 subtype detection, not " |  | ||||||
|                             + "available! Assuming that it is a HX device"); |  | ||||||
|                     mDeviceType = DEVICE_TYPE_HX; |  | ||||||
|                 } catch (Exception e) { |  | ||||||
|                     Log.e(TAG, "An unexpected exception occured while trying " |  | ||||||
|                             + "to detect PL2303 subtype", e); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             setControlLines(mControlLinesValue); |  | ||||||
|             resetDevice(); |  | ||||||
| 
 |  | ||||||
|             doBlackMagic(); |  | ||||||
|             openSuccessful = true; |  | ||||||
|         } finally { |  | ||||||
|             if (!openSuccessful) { |  | ||||||
|               try { |  | ||||||
|                 mConnection.releaseInterface(usbInterface); |  | ||||||
|               } catch (Exception ingored) { |  | ||||||
|                 // Do not cover possible exceptions |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void close() throws IOException { |  | ||||||
|         try { |  | ||||||
|             mStopReadStatusThread = true; |  | ||||||
|             synchronized (mReadStatusThreadLock) { |  | ||||||
|                 if (mReadStatusThread != null) { |  | ||||||
|                     try { |  | ||||||
|                         mReadStatusThread.join(); |  | ||||||
|                     } catch (Exception e) { |  | ||||||
|                         Log.w(TAG, "An error occured while waiting for status read thread", e); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             resetDevice(); |  | ||||||
|         } finally { |  | ||||||
|             mConnection.releaseInterface(mDevice.getInterface(0)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public int read(byte[] dest, int timeoutMillis) throws IOException { |  | ||||||
|         synchronized (mReadBufferLock) { |  | ||||||
|             int readAmt = Math.min(dest.length, mReadBuffer.length); |  | ||||||
|             int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, |  | ||||||
|                     readAmt, timeoutMillis); |  | ||||||
|             if (numBytesRead < 0) { |  | ||||||
|                 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); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             offset += amtWritten; |  | ||||||
|         } |  | ||||||
|         return offset; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setParameters(int baudRate, int dataBits, int stopBits, |  | ||||||
|             int parity) throws IOException { |  | ||||||
|         if ((mBaudRate == baudRate) && (mDataBits == dataBits) |  | ||||||
|                 && (mStopBits == stopBits) && (mParity == parity)) { |  | ||||||
|             // Make sure no action is performed if there is nothing to change |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         byte[] lineRequestData = new byte[7]; |  | ||||||
| 
 |  | ||||||
|         lineRequestData[0] = (byte) (baudRate & 0xff); |  | ||||||
|         lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff); |  | ||||||
|         lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff); |  | ||||||
|         lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff); |  | ||||||
| 
 |  | ||||||
|         switch (stopBits) { |  | ||||||
|         case STOPBITS_1: |  | ||||||
|             lineRequestData[4] = 0; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case STOPBITS_1_5: |  | ||||||
|             lineRequestData[4] = 1; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case STOPBITS_2: |  | ||||||
|             lineRequestData[4] = 2; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         default: |  | ||||||
|             throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         switch (parity) { |  | ||||||
|         case PARITY_NONE: |  | ||||||
|             lineRequestData[5] = 0; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case PARITY_ODD: |  | ||||||
|             lineRequestData[5] = 1; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case PARITY_EVEN: |  | ||||||
|             lineRequestData[5] = 2; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case PARITY_MARK: |  | ||||||
|             lineRequestData[5] = 3; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         case PARITY_SPACE: |  | ||||||
|             lineRequestData[5] = 4; |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         default: |  | ||||||
|             throw new IllegalArgumentException("Unknown parity value: " + parity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         lineRequestData[6] = (byte) dataBits; |  | ||||||
| 
 |  | ||||||
|         ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData); |  | ||||||
| 
 |  | ||||||
|         resetDevice(); |  | ||||||
| 
 |  | ||||||
|         mBaudRate = baudRate; |  | ||||||
|         mDataBits = dataBits; |  | ||||||
|         mStopBits = stopBits; |  | ||||||
|         mParity = parity; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getCD() throws IOException { |  | ||||||
|         return testStatusFlag(STATUS_FLAG_CD); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getCTS() throws IOException { |  | ||||||
|         return testStatusFlag(STATUS_FLAG_CTS); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getDSR() throws IOException { |  | ||||||
|         return testStatusFlag(STATUS_FLAG_DSR); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getDTR() throws IOException { |  | ||||||
|         return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setDTR(boolean value) throws IOException { |  | ||||||
|         int newControlLinesValue; |  | ||||||
|         if (value) { |  | ||||||
|             newControlLinesValue = mControlLinesValue | CONTROL_DTR; |  | ||||||
|         } else { |  | ||||||
|             newControlLinesValue = mControlLinesValue & ~CONTROL_DTR; |  | ||||||
|         } |  | ||||||
|         setControlLines(newControlLinesValue); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRI() throws IOException { |  | ||||||
|         return testStatusFlag(STATUS_FLAG_RI); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean getRTS() throws IOException { |  | ||||||
|         return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public void setRTS(boolean value) throws IOException { |  | ||||||
|         int newControlLinesValue; |  | ||||||
|         if (value) { |  | ||||||
|             newControlLinesValue = mControlLinesValue | CONTROL_RTS; |  | ||||||
|         } else { |  | ||||||
|             newControlLinesValue = mControlLinesValue & ~CONTROL_RTS; |  | ||||||
|         } |  | ||||||
|         setControlLines(newControlLinesValue); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException { |  | ||||||
|         if (purgeReadBuffers) { |  | ||||||
|             vendorOut(FLUSH_RX_REQUEST, 0, null); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (purgeWriteBuffers) { |  | ||||||
|             vendorOut(FLUSH_TX_REQUEST, 0, null); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static Map<Integer, int[]> getSupportedDevices() { |  | ||||||
|         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); |  | ||||||
|         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_PROLIFIC), |  | ||||||
|                 new int[] { UsbId.PROLIFIC_PL2303, }); |  | ||||||
|         return supportedDevices; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,247 +0,0 @@ | |||||||
| /* 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.UsbDevice; |  | ||||||
| import android.hardware.usb.UsbDeviceConnection; |  | ||||||
| import android.hardware.usb.UsbManager; |  | ||||||
| 
 |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Helper class which finds compatible {@link UsbDevice}s and creates |  | ||||||
|  * {@link UsbSerialDriver} instances. |  | ||||||
|  * |  | ||||||
|  * <p/> |  | ||||||
|  * You don't need a Prober to use the rest of the library: it is perfectly |  | ||||||
|  * acceptable to instantiate driver instances manually. The Prober simply |  | ||||||
|  * provides convenience functions. |  | ||||||
|  * |  | ||||||
|  * <p/> |  | ||||||
|  * For most drivers, the corresponding {@link #probe(UsbManager, UsbDevice)} |  | ||||||
|  * method will either return an empty list (device unknown / unsupported) or a |  | ||||||
|  * singleton list. However, multi-port drivers may return multiple instances. |  | ||||||
|  * |  | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  | ||||||
|  */ |  | ||||||
| public enum UsbSerialProber { |  | ||||||
| 
 |  | ||||||
|     // TODO(mikey): Too much boilerplate. |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Prober for {@link FtdiSerialDriver}. |  | ||||||
|      * |  | ||||||
|      * @see FtdiSerialDriver |  | ||||||
|      */ |  | ||||||
|     FTDI_SERIAL { |  | ||||||
|         @Override |  | ||||||
|         public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) { |  | ||||||
|             if (!testIfSupported(usbDevice, FtdiSerialDriver.getSupportedDevices())) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbDeviceConnection connection = manager.openDevice(usbDevice); |  | ||||||
|             if (connection == null) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbSerialDriver driver = new FtdiSerialDriver(usbDevice, connection); |  | ||||||
|             return Collections.singletonList(driver); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     CDC_ACM_SERIAL { |  | ||||||
|         @Override |  | ||||||
|         public List<UsbSerialDriver> probe(UsbManager manager, UsbDevice usbDevice) { |  | ||||||
|             if (!testIfSupported(usbDevice, CdcAcmSerialDriver.getSupportedDevices())) { |  | ||||||
|                return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbDeviceConnection connection = manager.openDevice(usbDevice); |  | ||||||
|             if (connection == null) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbSerialDriver driver = new CdcAcmSerialDriver(usbDevice, connection); |  | ||||||
|             return Collections.singletonList(driver); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     SILAB_SERIAL { |  | ||||||
|         @Override |  | ||||||
|         public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) { |  | ||||||
|             if (!testIfSupported(usbDevice, Cp2102SerialDriver.getSupportedDevices())) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbDeviceConnection connection = manager.openDevice(usbDevice); |  | ||||||
|             if (connection == null) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbSerialDriver driver = new Cp2102SerialDriver(usbDevice, connection); |  | ||||||
|             return Collections.singletonList(driver); |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     PROLIFIC_SERIAL { |  | ||||||
|         @Override |  | ||||||
|         public List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice) { |  | ||||||
|             if (!testIfSupported(usbDevice, ProlificSerialDriver.getSupportedDevices())) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbDeviceConnection connection = manager.openDevice(usbDevice); |  | ||||||
|             if (connection == null) { |  | ||||||
|                 return Collections.emptyList(); |  | ||||||
|             } |  | ||||||
|             final UsbSerialDriver driver = new ProlificSerialDriver(usbDevice, connection); |  | ||||||
|             return Collections.singletonList(driver); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Tests the supplied {@link UsbDevice} for compatibility with this enum |  | ||||||
|      * member, returning one or more driver instances if compatible. |  | ||||||
|      * |  | ||||||
|      * @param manager the {@link UsbManager} to use |  | ||||||
|      * @param usbDevice the raw {@link UsbDevice} to use |  | ||||||
|      * @return zero or more {@link UsbSerialDriver}, depending on compatibility |  | ||||||
|      *         (never {@code null}). |  | ||||||
|      */ |  | ||||||
|     protected abstract List<UsbSerialDriver> probe(final UsbManager manager, final UsbDevice usbDevice); |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Creates and returns a new {@link UsbSerialDriver} instance for the first |  | ||||||
|      * compatible {@link UsbDevice} found on the bus.  If none are found, |  | ||||||
|      * returns {@code null}. |  | ||||||
|      * |  | ||||||
|      * <p/> |  | ||||||
|      * The order of devices is undefined, therefore if there are multiple |  | ||||||
|      * devices on the bus, the chosen device may not be predictable (clients |  | ||||||
|      * should use {@link #findAllDevices(UsbManager)} instead). |  | ||||||
|      * |  | ||||||
|      * @param usbManager the {@link UsbManager} to use. |  | ||||||
|      * @return the first available {@link UsbSerialDriver}, or {@code null} if |  | ||||||
|      *         none are available. |  | ||||||
|      */ |  | ||||||
|     public static UsbSerialDriver findFirstDevice(final UsbManager usbManager) { |  | ||||||
|         for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) { |  | ||||||
|             for (final UsbSerialProber prober : values()) { |  | ||||||
|                 final List<UsbSerialDriver> probedDevices = prober.probe(usbManager, usbDevice); |  | ||||||
|                 if (!probedDevices.isEmpty()) { |  | ||||||
|                     return probedDevices.get(0); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Creates a new {@link UsbSerialDriver} instance for all compatible |  | ||||||
|      * {@link UsbDevice}s found on the bus. If no compatible devices are found, |  | ||||||
|      * the list will be empty. |  | ||||||
|      * |  | ||||||
|      * @param usbManager |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     public static List<UsbSerialDriver> findAllDevices(final UsbManager usbManager) { |  | ||||||
|         final List<UsbSerialDriver> result = new ArrayList<UsbSerialDriver>(); |  | ||||||
| 
 |  | ||||||
|         // For each UsbDevice, call probe() for each prober. |  | ||||||
|         for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) { |  | ||||||
|             result.addAll(probeSingleDevice(usbManager, usbDevice)); |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Special method for testing a specific device for driver support, |  | ||||||
|      * returning any compatible driver(s). |  | ||||||
|      * |  | ||||||
|      * <p/> |  | ||||||
|      * Clients should ordinarily use {@link #findAllDevices(UsbManager)}, which |  | ||||||
|      * operates against the entire bus of devices. This method is useful when |  | ||||||
|      * testing against only a single target is desired. |  | ||||||
|      * |  | ||||||
|      * @param usbManager the {@link UsbManager} to use. |  | ||||||
|      * @param usbDevice the device to test against. |  | ||||||
|      * @return a list containing zero or more {@link UsbSerialDriver} instances. |  | ||||||
|      */ |  | ||||||
|     public static List<UsbSerialDriver> probeSingleDevice(final UsbManager usbManager, |  | ||||||
|             UsbDevice usbDevice) { |  | ||||||
|         final List<UsbSerialDriver> result = new ArrayList<UsbSerialDriver>(); |  | ||||||
|         for (final UsbSerialProber prober : values()) { |  | ||||||
|             final List<UsbSerialDriver> probedDevices = prober.probe(usbManager, usbDevice); |  | ||||||
|             result.addAll(probedDevices); |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Deprecated; Use {@link #findFirstDevice(UsbManager)}. |  | ||||||
|      * |  | ||||||
|      * @param usbManager |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     @Deprecated |  | ||||||
|     public static UsbSerialDriver acquire(final UsbManager usbManager) { |  | ||||||
|         return findFirstDevice(usbManager); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Deprecated; use {@link #probeSingleDevice(UsbManager, UsbDevice)}. |  | ||||||
|      * |  | ||||||
|      * @param usbManager |  | ||||||
|      * @param usbDevice |  | ||||||
|      * @return |  | ||||||
|      */ |  | ||||||
|     @Deprecated |  | ||||||
|     public static UsbSerialDriver acquire(final UsbManager usbManager, final UsbDevice usbDevice) { |  | ||||||
|         final List<UsbSerialDriver> probedDevices = probeSingleDevice(usbManager, usbDevice); |  | ||||||
|         if (!probedDevices.isEmpty()) { |  | ||||||
|             return probedDevices.get(0); |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Returns {@code true} if the given device is found in the driver's |  | ||||||
|      * vendor/product map. |  | ||||||
|      * |  | ||||||
|      * @param usbDevice the device to test |  | ||||||
|      * @param supportedDevices map of vendor IDs to product ID(s) |  | ||||||
|      * @return {@code true} if supported |  | ||||||
|      */ |  | ||||||
|     private static boolean testIfSupported(final UsbDevice usbDevice, |  | ||||||
|             final Map<Integer, int[]> supportedDevices) { |  | ||||||
|         final int[] supportedProducts = supportedDevices.get( |  | ||||||
|                 Integer.valueOf(usbDevice.getVendorId())); |  | ||||||
|         if (supportedProducts == null) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         final int productId = usbDevice.getProductId(); |  | ||||||
|         for (int supportedProductId : supportedProducts) { |  | ||||||
|             if (productId == supportedProductId) { |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										15
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | // Top-level build file where you can add configuration options common to all sub-projects/modules. | ||||||
|  | buildscript { | ||||||
|  |     repositories { | ||||||
|  |         mavenCentral() | ||||||
|  |     } | ||||||
|  |     dependencies { | ||||||
|  |         classpath 'com.android.tools.build:gradle:0.9.+' | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | allprojects { | ||||||
|  |     repositories { | ||||||
|  |         mavenCentral() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | #Wed Apr 10 15:27:10 PDT 2013 | ||||||
|  | distributionBase=GRADLE_USER_HOME | ||||||
|  | distributionPath=wrapper/dists | ||||||
|  | zipStoreBase=GRADLE_USER_HOME | ||||||
|  | zipStorePath=wrapper/dists | ||||||
|  | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip | ||||||
							
								
								
									
										164
									
								
								gradlew
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										164
									
								
								gradlew
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @ -0,0 +1,164 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  | 
 | ||||||
|  | ############################################################################## | ||||||
|  | ## | ||||||
|  | ##  Gradle start up script for UN*X | ||||||
|  | ## | ||||||
|  | ############################################################################## | ||||||
|  | 
 | ||||||
|  | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | DEFAULT_JVM_OPTS="" | ||||||
|  | 
 | ||||||
|  | APP_NAME="Gradle" | ||||||
|  | APP_BASE_NAME=`basename "$0"` | ||||||
|  | 
 | ||||||
|  | # Use the maximum available, or set MAX_FD != -1 to use that value. | ||||||
|  | MAX_FD="maximum" | ||||||
|  | 
 | ||||||
|  | warn ( ) { | ||||||
|  |     echo "$*" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | die ( ) { | ||||||
|  |     echo | ||||||
|  |     echo "$*" | ||||||
|  |     echo | ||||||
|  |     exit 1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # OS specific support (must be 'true' or 'false'). | ||||||
|  | cygwin=false | ||||||
|  | msys=false | ||||||
|  | darwin=false | ||||||
|  | case "`uname`" in | ||||||
|  |   CYGWIN* ) | ||||||
|  |     cygwin=true | ||||||
|  |     ;; | ||||||
|  |   Darwin* ) | ||||||
|  |     darwin=true | ||||||
|  |     ;; | ||||||
|  |   MINGW* ) | ||||||
|  |     msys=true | ||||||
|  |     ;; | ||||||
|  | esac | ||||||
|  | 
 | ||||||
|  | # For Cygwin, ensure paths are in UNIX format before anything is touched. | ||||||
|  | if $cygwin ; then | ||||||
|  |     [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Attempt to set APP_HOME | ||||||
|  | # Resolve links: $0 may be a link | ||||||
|  | PRG="$0" | ||||||
|  | # Need this for relative symlinks. | ||||||
|  | while [ -h "$PRG" ] ; do | ||||||
|  |     ls=`ls -ld "$PRG"` | ||||||
|  |     link=`expr "$ls" : '.*-> \(.*\)$'` | ||||||
|  |     if expr "$link" : '/.*' > /dev/null; then | ||||||
|  |         PRG="$link" | ||||||
|  |     else | ||||||
|  |         PRG=`dirname "$PRG"`"/$link" | ||||||
|  |     fi | ||||||
|  | done | ||||||
|  | SAVED="`pwd`" | ||||||
|  | cd "`dirname \"$PRG\"`/" >&- | ||||||
|  | APP_HOME="`pwd -P`" | ||||||
|  | cd "$SAVED" >&- | ||||||
|  | 
 | ||||||
|  | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | # Determine the Java command to use to start the JVM. | ||||||
|  | if [ -n "$JAVA_HOME" ] ; then | ||||||
|  |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | ||||||
|  |         # IBM's JDK on AIX uses strange locations for the executables | ||||||
|  |         JAVACMD="$JAVA_HOME/jre/sh/java" | ||||||
|  |     else | ||||||
|  |         JAVACMD="$JAVA_HOME/bin/java" | ||||||
|  |     fi | ||||||
|  |     if [ ! -x "$JAVACMD" ] ; then | ||||||
|  |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  |     fi | ||||||
|  | else | ||||||
|  |     JAVACMD="java" | ||||||
|  |     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
|  | 
 | ||||||
|  | Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | location of your Java installation." | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Increase the maximum file descriptors if we can. | ||||||
|  | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then | ||||||
|  |     MAX_FD_LIMIT=`ulimit -H -n` | ||||||
|  |     if [ $? -eq 0 ] ; then | ||||||
|  |         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | ||||||
|  |             MAX_FD="$MAX_FD_LIMIT" | ||||||
|  |         fi | ||||||
|  |         ulimit -n $MAX_FD | ||||||
|  |         if [ $? -ne 0 ] ; then | ||||||
|  |             warn "Could not set maximum file descriptor limit: $MAX_FD" | ||||||
|  |         fi | ||||||
|  |     else | ||||||
|  |         warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | ||||||
|  |     fi | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # For Darwin, add options to specify how the application appears in the dock | ||||||
|  | if $darwin; then | ||||||
|  |     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # For Cygwin, switch paths to Windows format before running java | ||||||
|  | if $cygwin ; then | ||||||
|  |     APP_HOME=`cygpath --path --mixed "$APP_HOME"` | ||||||
|  |     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | ||||||
|  | 
 | ||||||
|  |     # We build the pattern for arguments to be converted via cygpath | ||||||
|  |     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | ||||||
|  |     SEP="" | ||||||
|  |     for dir in $ROOTDIRSRAW ; do | ||||||
|  |         ROOTDIRS="$ROOTDIRS$SEP$dir" | ||||||
|  |         SEP="|" | ||||||
|  |     done | ||||||
|  |     OURCYGPATTERN="(^($ROOTDIRS))" | ||||||
|  |     # Add a user-defined pattern to the cygpath arguments | ||||||
|  |     if [ "$GRADLE_CYGPATTERN" != "" ] ; then | ||||||
|  |         OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | ||||||
|  |     fi | ||||||
|  |     # Now convert the arguments - kludge to limit ourselves to /bin/sh | ||||||
|  |     i=0 | ||||||
|  |     for arg in "$@" ; do | ||||||
|  |         CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | ||||||
|  |         CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option | ||||||
|  | 
 | ||||||
|  |         if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition | ||||||
|  |             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | ||||||
|  |         else | ||||||
|  |             eval `echo args$i`="\"$arg\"" | ||||||
|  |         fi | ||||||
|  |         i=$((i+1)) | ||||||
|  |     done | ||||||
|  |     case $i in | ||||||
|  |         (0) set -- ;; | ||||||
|  |         (1) set -- "$args0" ;; | ||||||
|  |         (2) set -- "$args0" "$args1" ;; | ||||||
|  |         (3) set -- "$args0" "$args1" "$args2" ;; | ||||||
|  |         (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | ||||||
|  |         (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | ||||||
|  |         (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | ||||||
|  |         (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | ||||||
|  |         (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | ||||||
|  |         (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | ||||||
|  |     esac | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules | ||||||
|  | function splitJvmOpts() { | ||||||
|  |     JVM_OPTS=("$@") | ||||||
|  | } | ||||||
|  | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS | ||||||
|  | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" | ||||||
|  | 
 | ||||||
|  | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" | ||||||
							
								
								
									
										90
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | |||||||
|  | @if "%DEBUG%" == "" @echo off | ||||||
|  | @rem ########################################################################## | ||||||
|  | @rem | ||||||
|  | @rem  Gradle startup script for Windows | ||||||
|  | @rem | ||||||
|  | @rem ########################################################################## | ||||||
|  | 
 | ||||||
|  | @rem Set local scope for the variables with windows NT shell | ||||||
|  | if "%OS%"=="Windows_NT" setlocal | ||||||
|  | 
 | ||||||
|  | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | ||||||
|  | set DEFAULT_JVM_OPTS= | ||||||
|  | 
 | ||||||
|  | set DIRNAME=%~dp0 | ||||||
|  | if "%DIRNAME%" == "" set DIRNAME=. | ||||||
|  | set APP_BASE_NAME=%~n0 | ||||||
|  | set APP_HOME=%DIRNAME% | ||||||
|  | 
 | ||||||
|  | @rem Find java.exe | ||||||
|  | if defined JAVA_HOME goto findJavaFromJavaHome | ||||||
|  | 
 | ||||||
|  | set JAVA_EXE=java.exe | ||||||
|  | %JAVA_EXE% -version >NUL 2>&1 | ||||||
|  | if "%ERRORLEVEL%" == "0" goto init | ||||||
|  | 
 | ||||||
|  | echo. | ||||||
|  | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | ||||||
|  | echo. | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | echo location of your Java installation. | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :findJavaFromJavaHome | ||||||
|  | set JAVA_HOME=%JAVA_HOME:"=% | ||||||
|  | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | ||||||
|  | 
 | ||||||
|  | if exist "%JAVA_EXE%" goto init | ||||||
|  | 
 | ||||||
|  | echo. | ||||||
|  | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | ||||||
|  | echo. | ||||||
|  | echo Please set the JAVA_HOME variable in your environment to match the | ||||||
|  | echo location of your Java installation. | ||||||
|  | 
 | ||||||
|  | goto fail | ||||||
|  | 
 | ||||||
|  | :init | ||||||
|  | @rem Get command-line arguments, handling Windowz variants | ||||||
|  | 
 | ||||||
|  | if not "%OS%" == "Windows_NT" goto win9xME_args | ||||||
|  | if "%@eval[2+2]" == "4" goto 4NT_args | ||||||
|  | 
 | ||||||
|  | :win9xME_args | ||||||
|  | @rem Slurp the command line arguments. | ||||||
|  | set CMD_LINE_ARGS= | ||||||
|  | set _SKIP=2 | ||||||
|  | 
 | ||||||
|  | :win9xME_args_slurp | ||||||
|  | if "x%~1" == "x" goto execute | ||||||
|  | 
 | ||||||
|  | set CMD_LINE_ARGS=%* | ||||||
|  | goto execute | ||||||
|  | 
 | ||||||
|  | :4NT_args | ||||||
|  | @rem Get arguments from the 4NT Shell from JP Software | ||||||
|  | set CMD_LINE_ARGS=%$ | ||||||
|  | 
 | ||||||
|  | :execute | ||||||
|  | @rem Setup the command line | ||||||
|  | 
 | ||||||
|  | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | ||||||
|  | 
 | ||||||
|  | @rem Execute Gradle | ||||||
|  | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | ||||||
|  | 
 | ||||||
|  | :end | ||||||
|  | @rem End local scope for the variables with windows NT shell | ||||||
|  | if "%ERRORLEVEL%"=="0" goto mainEnd | ||||||
|  | 
 | ||||||
|  | :fail | ||||||
|  | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | ||||||
|  | rem the _cmd.exe /c_ return code! | ||||||
|  | if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | ||||||
|  | exit /b 1 | ||||||
|  | 
 | ||||||
|  | :mainEnd | ||||||
|  | if "%OS%"=="Windows_NT" endlocal | ||||||
|  | 
 | ||||||
|  | :omega | ||||||
							
								
								
									
										1
									
								
								settings.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								settings.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | include 'usbSerialForAndroid', 'usbSerialExamples' | ||||||
							
								
								
									
										24
									
								
								usbSerialExamples/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								usbSerialExamples/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | apply plugin: 'android' | ||||||
|  | 
 | ||||||
|  | android { | ||||||
|  |     compileSdkVersion 19 | ||||||
|  |     buildToolsVersion "19.0.3" | ||||||
|  | 
 | ||||||
|  |     defaultConfig { | ||||||
|  |         minSdkVersion 14 | ||||||
|  |         targetSdkVersion 19 | ||||||
|  | 
 | ||||||
|  |         testPackageName "com.hoho.android.usbserial.examples" | ||||||
|  |         testInstrumentationRunner "android.test.InstrumentationTestRunner" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     buildTypes { | ||||||
|  |         release { | ||||||
|  |             runProguard true | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | dependencies { | ||||||
|  |     compile project(':usbSerialForAndroid') | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2011 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,7 +16,7 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.hoho.android.usbserial.examples; | package com.hoho.android.usbserial.examples; | ||||||
| @ -41,6 +42,7 @@ import android.widget.TextView; | |||||||
| import android.widget.TwoLineListItem; | import android.widget.TwoLineListItem; | ||||||
| 
 | 
 | ||||||
| import com.hoho.android.usbserial.driver.UsbSerialDriver; | import com.hoho.android.usbserial.driver.UsbSerialDriver; | ||||||
|  | import com.hoho.android.usbserial.driver.UsbSerialPort; | ||||||
| import com.hoho.android.usbserial.driver.UsbSerialProber; | import com.hoho.android.usbserial.driver.UsbSerialProber; | ||||||
| import com.hoho.android.usbserial.util.HexDump; | import com.hoho.android.usbserial.util.HexDump; | ||||||
| 
 | 
 | ||||||
| @ -80,19 +82,8 @@ public class DeviceListActivity extends Activity { | |||||||
| 
 | 
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     /** Simple container for a UsbDevice and its driver. */ |     private List<UsbSerialPort> mEntries = new ArrayList<UsbSerialPort>(); | ||||||
|     private static class DeviceEntry { |     private ArrayAdapter<UsbSerialPort> mAdapter; | ||||||
|         public UsbDevice device; |  | ||||||
|         public UsbSerialDriver driver; |  | ||||||
| 
 |  | ||||||
|         DeviceEntry(UsbDevice device, UsbSerialDriver driver) { |  | ||||||
|             this.device = device; |  | ||||||
|             this.driver = driver; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private List<DeviceEntry> mEntries = new ArrayList<DeviceEntry>(); |  | ||||||
|     private ArrayAdapter<DeviceEntry> mAdapter; |  | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void onCreate(Bundle savedInstanceState) { |     public void onCreate(Bundle savedInstanceState) { | ||||||
| @ -104,7 +95,8 @@ public class DeviceListActivity extends Activity { | |||||||
|         mProgressBar = (ProgressBar) findViewById(R.id.progressBar); |         mProgressBar = (ProgressBar) findViewById(R.id.progressBar); | ||||||
|         mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle); |         mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle); | ||||||
| 
 | 
 | ||||||
|         mAdapter = new ArrayAdapter<DeviceEntry>(this, android.R.layout.simple_expandable_list_item_2, mEntries) { |         mAdapter = new ArrayAdapter<UsbSerialPort>(this, | ||||||
|  |                 android.R.layout.simple_expandable_list_item_2, mEntries) { | ||||||
|             @Override |             @Override | ||||||
|             public View getView(int position, View convertView, ViewGroup parent) { |             public View getView(int position, View convertView, ViewGroup parent) { | ||||||
|                 final TwoLineListItem row; |                 final TwoLineListItem row; | ||||||
| @ -116,14 +108,16 @@ public class DeviceListActivity extends Activity { | |||||||
|                     row = (TwoLineListItem) convertView; |                     row = (TwoLineListItem) convertView; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 final DeviceEntry entry = mEntries.get(position); |                 final UsbSerialPort port = mEntries.get(position); | ||||||
|  |                 final UsbSerialDriver driver = port.getDriver(); | ||||||
|  |                 final UsbDevice device = driver.getDevice(); | ||||||
|  | 
 | ||||||
|                 final String title = String.format("Vendor %s Product %s", |                 final String title = String.format("Vendor %s Product %s", | ||||||
|                         HexDump.toHexString((short) entry.device.getVendorId()), |                         HexDump.toHexString((short) device.getVendorId()), | ||||||
|                         HexDump.toHexString((short) entry.device.getProductId())); |                         HexDump.toHexString((short) device.getProductId())); | ||||||
|                 row.getText1().setText(title); |                 row.getText1().setText(title); | ||||||
| 
 | 
 | ||||||
|                 final String subtitle = entry.driver != null ? |                 final String subtitle = driver.getClass().getSimpleName(); | ||||||
|                         entry.driver.getClass().getSimpleName() : "No Driver"; |  | ||||||
|                 row.getText2().setText(subtitle); |                 row.getText2().setText(subtitle); | ||||||
| 
 | 
 | ||||||
|                 return row; |                 return row; | ||||||
| @ -141,14 +135,8 @@ public class DeviceListActivity extends Activity { | |||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 final DeviceEntry entry = mEntries.get(position); |                 final UsbSerialPort port = mEntries.get(position); | ||||||
|                 final UsbSerialDriver driver = entry.driver; |                 showConsoleActivity(port); | ||||||
|                 if (driver == null) { |  | ||||||
|                     Log.d(TAG, "No driver."); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 showConsoleActivity(driver); |  | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -168,31 +156,28 @@ public class DeviceListActivity extends Activity { | |||||||
|     private void refreshDeviceList() { |     private void refreshDeviceList() { | ||||||
|         showProgressBar(); |         showProgressBar(); | ||||||
| 
 | 
 | ||||||
|         new AsyncTask<Void, Void, List<DeviceEntry>>() { |         new AsyncTask<Void, Void, List<UsbSerialPort>>() { | ||||||
|             @Override |             @Override | ||||||
|             protected List<DeviceEntry> doInBackground(Void... params) { |             protected List<UsbSerialPort> doInBackground(Void... params) { | ||||||
|                 Log.d(TAG, "Refreshing device list ..."); |                 Log.d(TAG, "Refreshing device list ..."); | ||||||
|                 SystemClock.sleep(1000); |                 SystemClock.sleep(1000); | ||||||
|                 final List<DeviceEntry> result = new ArrayList<DeviceEntry>(); | 
 | ||||||
|                 for (final UsbDevice device : mUsbManager.getDeviceList().values()) { |                 final List<UsbSerialDriver> drivers = | ||||||
|                     final List<UsbSerialDriver> drivers = |                         UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager); | ||||||
|                             UsbSerialProber.probeSingleDevice(mUsbManager, device); | 
 | ||||||
|                     Log.d(TAG, "Found usb device: " + device); |                 final List<UsbSerialPort> result = new ArrayList<UsbSerialPort>(); | ||||||
|                     if (drivers.isEmpty()) { |                 for (final UsbSerialDriver driver : drivers) { | ||||||
|                         Log.d(TAG, "  - No UsbSerialDriver available."); |                     final List<UsbSerialPort> ports = driver.getPorts(); | ||||||
|                         result.add(new DeviceEntry(device, null)); |                     Log.d(TAG, String.format("+ %s: %s port%s", | ||||||
|                     } else { |                             driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s")); | ||||||
|                         for (UsbSerialDriver driver : drivers) { |                     result.addAll(ports); | ||||||
|                             Log.d(TAG, "  + " + driver); |  | ||||||
|                             result.add(new DeviceEntry(device, driver)); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|                 return result; |                 return result; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             @Override |             @Override | ||||||
|             protected void onPostExecute(List<DeviceEntry> result) { |             protected void onPostExecute(List<UsbSerialPort> result) { | ||||||
|                 mEntries.clear(); |                 mEntries.clear(); | ||||||
|                 mEntries.addAll(result); |                 mEntries.addAll(result); | ||||||
|                 mAdapter.notifyDataSetChanged(); |                 mAdapter.notifyDataSetChanged(); | ||||||
| @ -214,8 +199,8 @@ public class DeviceListActivity extends Activity { | |||||||
|         mProgressBar.setVisibility(View.INVISIBLE); |         mProgressBar.setVisibility(View.INVISIBLE); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void showConsoleActivity(UsbSerialDriver driver) { |     private void showConsoleActivity(UsbSerialPort port) { | ||||||
|         SerialConsoleActivity.show(this, driver); |         SerialConsoleActivity.show(this, port); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2011 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,7 +16,7 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.hoho.android.usbserial.examples; | package com.hoho.android.usbserial.examples; | ||||||
| @ -23,12 +24,14 @@ package com.hoho.android.usbserial.examples; | |||||||
| import android.app.Activity; | import android.app.Activity; | ||||||
| import android.content.Context; | import android.content.Context; | ||||||
| import android.content.Intent; | import android.content.Intent; | ||||||
|  | import android.hardware.usb.UsbDeviceConnection; | ||||||
|  | import android.hardware.usb.UsbManager; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| import android.widget.ScrollView; | import android.widget.ScrollView; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| 
 | 
 | ||||||
| import com.hoho.android.usbserial.driver.UsbSerialDriver; | import com.hoho.android.usbserial.driver.UsbSerialPort; | ||||||
| import com.hoho.android.usbserial.util.HexDump; | import com.hoho.android.usbserial.util.HexDump; | ||||||
| import com.hoho.android.usbserial.util.SerialInputOutputManager; | import com.hoho.android.usbserial.util.SerialInputOutputManager; | ||||||
| 
 | 
 | ||||||
| @ -37,7 +40,7 @@ import java.util.concurrent.ExecutorService; | |||||||
| import java.util.concurrent.Executors; | import java.util.concurrent.Executors; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Monitors a single {@link UsbSerialDriver} instance, showing all data |  * Monitors a single {@link UsbSerialPort} instance, showing all data | ||||||
|  * received. |  * received. | ||||||
|  * |  * | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  * @author mike wakerly (opensource@hoho.com) | ||||||
| @ -48,7 +51,7 @@ public class SerialConsoleActivity extends Activity { | |||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Driver instance, passed in statically via |      * Driver instance, passed in statically via | ||||||
|      * {@link #show(Context, UsbSerialDriver)}. |      * {@link #show(Context, UsbSerialPort)}. | ||||||
|      * |      * | ||||||
|      * <p/> |      * <p/> | ||||||
|      * This is a devious hack; it'd be cleaner to re-create the driver using |      * This is a devious hack; it'd be cleaner to re-create the driver using | ||||||
| @ -56,7 +59,7 @@ public class SerialConsoleActivity extends Activity { | |||||||
|      * can get away with it because both activities will run in the same |      * can get away with it because both activities will run in the same | ||||||
|      * process, and this is a simple demo. |      * process, and this is a simple demo. | ||||||
|      */ |      */ | ||||||
|     private static UsbSerialDriver sDriver = null; |     private static UsbSerialPort sPort = null; | ||||||
| 
 | 
 | ||||||
|     private TextView mTitleTextView; |     private TextView mTitleTextView; | ||||||
|     private TextView mDumpTextView; |     private TextView mDumpTextView; | ||||||
| @ -98,13 +101,13 @@ public class SerialConsoleActivity extends Activity { | |||||||
|     protected void onPause() { |     protected void onPause() { | ||||||
|         super.onPause(); |         super.onPause(); | ||||||
|         stopIoManager(); |         stopIoManager(); | ||||||
|         if (sDriver != null) { |         if (sPort != null) { | ||||||
|             try { |             try { | ||||||
|                 sDriver.close(); |                 sPort.close(); | ||||||
|             } catch (IOException e) { |             } catch (IOException e) { | ||||||
|                 // Ignore. |                 // Ignore. | ||||||
|             } |             } | ||||||
|             sDriver = null; |             sPort = null; | ||||||
|         } |         } | ||||||
|         finish(); |         finish(); | ||||||
|     } |     } | ||||||
| @ -112,25 +115,33 @@ public class SerialConsoleActivity extends Activity { | |||||||
|     @Override |     @Override | ||||||
|     protected void onResume() { |     protected void onResume() { | ||||||
|         super.onResume(); |         super.onResume(); | ||||||
|         Log.d(TAG, "Resumed, sDriver=" + sDriver); |         Log.d(TAG, "Resumed, port=" + sPort); | ||||||
|         if (sDriver == null) { |         if (sPort == null) { | ||||||
|             mTitleTextView.setText("No serial device."); |             mTitleTextView.setText("No serial device."); | ||||||
|         } else { |         } else { | ||||||
|  |             final UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); | ||||||
|  | 
 | ||||||
|  |             UsbDeviceConnection connection = usbManager.openDevice(sPort.getDriver().getDevice()); | ||||||
|  |             if (connection == null) { | ||||||
|  |                 mTitleTextView.setText("Opening device failed"); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             try { |             try { | ||||||
|                 sDriver.open(); |                 sPort.open(connection); | ||||||
|                 sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE); |                 sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE); | ||||||
|             } catch (IOException e) { |             } catch (IOException e) { | ||||||
|                 Log.e(TAG, "Error setting up device: " + e.getMessage(), e); |                 Log.e(TAG, "Error setting up device: " + e.getMessage(), e); | ||||||
|                 mTitleTextView.setText("Error opening device: " + e.getMessage()); |                 mTitleTextView.setText("Error opening device: " + e.getMessage()); | ||||||
|                 try { |                 try { | ||||||
|                     sDriver.close(); |                     sPort.close(); | ||||||
|                 } catch (IOException e2) { |                 } catch (IOException e2) { | ||||||
|                     // Ignore. |                     // Ignore. | ||||||
|                 } |                 } | ||||||
|                 sDriver = null; |                 sPort = null; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             mTitleTextView.setText("Serial device: " + sDriver.getClass().getSimpleName()); |             mTitleTextView.setText("Serial device: " + sPort.getClass().getSimpleName()); | ||||||
|         } |         } | ||||||
|         onDeviceStateChange(); |         onDeviceStateChange(); | ||||||
|     } |     } | ||||||
| @ -144,9 +155,9 @@ public class SerialConsoleActivity extends Activity { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void startIoManager() { |     private void startIoManager() { | ||||||
|         if (sDriver != null) { |         if (sPort != null) { | ||||||
|             Log.i(TAG, "Starting io manager .."); |             Log.i(TAG, "Starting io manager .."); | ||||||
|             mSerialIoManager = new SerialInputOutputManager(sDriver, mListener); |             mSerialIoManager = new SerialInputOutputManager(sPort, mListener); | ||||||
|             mExecutor.submit(mSerialIoManager); |             mExecutor.submit(mSerialIoManager); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -169,8 +180,8 @@ public class SerialConsoleActivity extends Activity { | |||||||
|      * @param context |      * @param context | ||||||
|      * @param driver |      * @param driver | ||||||
|      */ |      */ | ||||||
|     static void show(Context context, UsbSerialDriver driver) { |     static void show(Context context, UsbSerialPort port) { | ||||||
|         sDriver = driver; |         sPort = port; | ||||||
|         final Intent intent = new Intent(context, SerialConsoleActivity.class); |         final Intent intent = new Intent(context, SerialConsoleActivity.class); | ||||||
|         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY); |         intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY); | ||||||
|         context.startActivity(intent); |         context.startActivity(intent); | ||||||
| Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB | 
| Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										18
									
								
								usbSerialForAndroid/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								usbSerialForAndroid/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | apply plugin: 'android-library' | ||||||
|  | 
 | ||||||
|  | android { | ||||||
|  |     compileSdkVersion 19 | ||||||
|  |     buildToolsVersion "19.1" | ||||||
|  | 
 | ||||||
|  |     defaultConfig { | ||||||
|  |         minSdkVersion 12 | ||||||
|  |         targetSdkVersion 19 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     buildTypes { | ||||||
|  |         release { | ||||||
|  |             runProguard false | ||||||
|  |             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,353 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/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.os.Build; | ||||||
|  | import android.util.Log; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.nio.ByteBuffer; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * USB CDC/ACM serial driver implementation. | ||||||
|  |  * | ||||||
|  |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  |  * @see <a | ||||||
|  |  *      href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf">Universal | ||||||
|  |  *      Serial Bus Class Definitions for Communication Devices, v1.1</a> | ||||||
|  |  */ | ||||||
|  | public class CdcAcmSerialDriver implements UsbSerialDriver { | ||||||
|  | 
 | ||||||
|  |     private final String TAG = CdcAcmSerialDriver.class.getSimpleName(); | ||||||
|  | 
 | ||||||
|  |     private final UsbDevice mDevice; | ||||||
|  |     private final UsbSerialPort mPort; | ||||||
|  | 
 | ||||||
|  |     public CdcAcmSerialDriver(UsbDevice device) { | ||||||
|  |         mDevice = device; | ||||||
|  |         mPort = new CdcAcmSerialPort(device, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UsbDevice getDevice() { | ||||||
|  |         return mDevice; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<UsbSerialPort> getPorts() { | ||||||
|  |         return Collections.singletonList(mPort); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     class CdcAcmSerialPort extends CommonUsbSerialPort { | ||||||
|  | 
 | ||||||
|  |         private final boolean mEnableAsyncReads; | ||||||
|  |         private UsbInterface mControlInterface; | ||||||
|  |         private UsbInterface mDataInterface; | ||||||
|  | 
 | ||||||
|  |         private UsbEndpoint mControlEndpoint; | ||||||
|  |         private UsbEndpoint mReadEndpoint; | ||||||
|  |         private UsbEndpoint mWriteEndpoint; | ||||||
|  | 
 | ||||||
|  |         private boolean mRts = false; | ||||||
|  |         private boolean mDtr = false; | ||||||
|  | 
 | ||||||
|  |         private static final int USB_RECIP_INTERFACE = 0x01; | ||||||
|  |         private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||||||
|  | 
 | ||||||
|  |         private static final int SET_LINE_CODING = 0x20;  // USB CDC 1.1 section 6.2 | ||||||
|  |         private static final int GET_LINE_CODING = 0x21; | ||||||
|  |         private static final int SET_CONTROL_LINE_STATE = 0x22; | ||||||
|  |         private static final int SEND_BREAK = 0x23; | ||||||
|  | 
 | ||||||
|  |         public CdcAcmSerialPort(UsbDevice device, int portNumber) { | ||||||
|  |             super(device, portNumber); | ||||||
|  |             mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public UsbSerialDriver getDriver() { | ||||||
|  |             return CdcAcmSerialDriver.this; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void open(UsbDeviceConnection connection) throws IOException { | ||||||
|  |             if (mConnection != null) { | ||||||
|  |                 throw new IOException("Already open"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             mConnection = connection; | ||||||
|  |             boolean opened = false; | ||||||
|  |             try { | ||||||
|  |                 Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); | ||||||
|  |                 mControlInterface = mDevice.getInterface(0); | ||||||
|  |                 Log.d(TAG, "Control iface=" + mControlInterface); | ||||||
|  |                 // class should be USB_CLASS_COMM | ||||||
|  | 
 | ||||||
|  |                 if (!mConnection.claimInterface(mControlInterface, true)) { | ||||||
|  |                     throw new IOException("Could not claim control interface."); | ||||||
|  |                 } | ||||||
|  |                 mControlEndpoint = mControlInterface.getEndpoint(0); | ||||||
|  |                 Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection()); | ||||||
|  | 
 | ||||||
|  |                 Log.d(TAG, "Claiming data interface."); | ||||||
|  |                 mDataInterface = mDevice.getInterface(1); | ||||||
|  |                 Log.d(TAG, "data iface=" + mDataInterface); | ||||||
|  |                 // class should be USB_CLASS_CDC_DATA | ||||||
|  | 
 | ||||||
|  |                 if (!mConnection.claimInterface(mDataInterface, true)) { | ||||||
|  |                     throw new IOException("Could not claim data interface."); | ||||||
|  |                 } | ||||||
|  |                 mReadEndpoint = mDataInterface.getEndpoint(1); | ||||||
|  |                 Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection()); | ||||||
|  |                 mWriteEndpoint = mDataInterface.getEndpoint(0); | ||||||
|  |                 Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection()); | ||||||
|  |                 if (mEnableAsyncReads) { | ||||||
|  |                   Log.d(TAG, "Async reads enabled"); | ||||||
|  |                 } else { | ||||||
|  |                   Log.d(TAG, "Async reads disabled."); | ||||||
|  |                 } | ||||||
|  |                 opened = true; | ||||||
|  |             } finally { | ||||||
|  |                 if (!opened) { | ||||||
|  |                     mConnection = null; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private int sendAcmControlMessage(int request, int value, byte[] buf) { | ||||||
|  |             return mConnection.controlTransfer( | ||||||
|  |                     USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void close() throws IOException { | ||||||
|  |             if (mConnection == null) { | ||||||
|  |                 throw new IOException("Already closed"); | ||||||
|  |             } | ||||||
|  |             mConnection.close(); | ||||||
|  |             mConnection = null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||||
|  |             if (mEnableAsyncReads) { | ||||||
|  |               final UsbRequest request = new UsbRequest(); | ||||||
|  |               try { | ||||||
|  |                 request.initialize(mConnection, mReadEndpoint); | ||||||
|  |                 final ByteBuffer buf = ByteBuffer.wrap(dest); | ||||||
|  |                 if (!request.queue(buf, dest.length)) { | ||||||
|  |                   throw new IOException("Error queueing request."); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 final UsbRequest response = mConnection.requestWait(); | ||||||
|  |                 if (response == null) { | ||||||
|  |                   throw new IOException("Null response"); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 final int nread = buf.position(); | ||||||
|  |                 if (nread > 0) { | ||||||
|  |                   //Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length))); | ||||||
|  |                   return nread; | ||||||
|  |                 } else { | ||||||
|  |                   return 0; | ||||||
|  |                 } | ||||||
|  |               } finally { | ||||||
|  |                 request.close(); | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             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 | ||||||
|  |                     if (timeoutMillis == Integer.MAX_VALUE) { | ||||||
|  |                         // Hack: Special case "~infinite timeout" as an error. | ||||||
|  |                         return -1; | ||||||
|  |                     } | ||||||
|  |                     return 0; | ||||||
|  |                 } | ||||||
|  |                 System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead); | ||||||
|  |             } | ||||||
|  |             return numBytesRead; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int write(byte[] src, int timeoutMillis) throws IOException { | ||||||
|  |             // TODO(mikey): Nearly identical to FtdiSerial write. Refactor. | ||||||
|  |             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 | ||||||
|  |         public void setParameters(int baudRate, int dataBits, int stopBits, int parity) { | ||||||
|  |             byte stopBitsByte; | ||||||
|  |             switch (stopBits) { | ||||||
|  |                 case STOPBITS_1: stopBitsByte = 0; break; | ||||||
|  |                 case STOPBITS_1_5: stopBitsByte = 1; break; | ||||||
|  |                 case STOPBITS_2: stopBitsByte = 2; break; | ||||||
|  |                 default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             byte parityBitesByte; | ||||||
|  |             switch (parity) { | ||||||
|  |                 case PARITY_NONE: parityBitesByte = 0; break; | ||||||
|  |                 case PARITY_ODD: parityBitesByte = 1; break; | ||||||
|  |                 case PARITY_EVEN: parityBitesByte = 2; break; | ||||||
|  |                 case PARITY_MARK: parityBitesByte = 3; break; | ||||||
|  |                 case PARITY_SPACE: parityBitesByte = 4; break; | ||||||
|  |                 default: throw new IllegalArgumentException("Bad value for parity: " + parity); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             byte[] msg = { | ||||||
|  |                     (byte) ( baudRate & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 8 ) & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 16) & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 24) & 0xff), | ||||||
|  |                     stopBitsByte, | ||||||
|  |                     parityBitesByte, | ||||||
|  |                     (byte) dataBits}; | ||||||
|  |             sendAcmControlMessage(SET_LINE_CODING, 0, msg); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getCD() throws IOException { | ||||||
|  |             return false;  // TODO | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getCTS() throws IOException { | ||||||
|  |             return false;  // TODO | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getDSR() throws IOException { | ||||||
|  |             return false;  // TODO | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getDTR() throws IOException { | ||||||
|  |             return mDtr; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setDTR(boolean value) throws IOException { | ||||||
|  |             mDtr = value; | ||||||
|  |             setDtrRts(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRI() throws IOException { | ||||||
|  |             return false;  // TODO | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRTS() throws IOException { | ||||||
|  |             return mRts; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setRTS(boolean value) throws IOException { | ||||||
|  |             mRts = value; | ||||||
|  |             setDtrRts(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void setDtrRts() { | ||||||
|  |             int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0); | ||||||
|  |             sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Map<Integer, int[]> getSupportedDevices() { | ||||||
|  |         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO), | ||||||
|  |                 new int[] { | ||||||
|  |                         UsbId.ARDUINO_UNO, | ||||||
|  |                         UsbId.ARDUINO_UNO_R3, | ||||||
|  |                         UsbId.ARDUINO_MEGA_2560, | ||||||
|  |                         UsbId.ARDUINO_MEGA_2560_R3, | ||||||
|  |                         UsbId.ARDUINO_SERIAL_ADAPTER, | ||||||
|  |                         UsbId.ARDUINO_SERIAL_ADAPTER_R3, | ||||||
|  |                         UsbId.ARDUINO_MEGA_ADK, | ||||||
|  |                         UsbId.ARDUINO_MEGA_ADK_R3, | ||||||
|  |                         UsbId.ARDUINO_LEONARDO, | ||||||
|  |                 }); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH), | ||||||
|  |                 new int[] { | ||||||
|  |                     UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL, | ||||||
|  |                 }); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ATMEL), | ||||||
|  |                 new int[] { | ||||||
|  |                     UsbId.ATMEL_LUFA_CDC_DEMO_APP, | ||||||
|  |                 }); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_LEAFLABS), | ||||||
|  |                 new int[] { | ||||||
|  |                     UsbId.LEAFLABS_MAPLE, | ||||||
|  |                 }); | ||||||
|  |         return supportedDevices; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2013 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,7 +16,7 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.hoho.android.usbserial.driver; | package com.hoho.android.usbserial.driver; | ||||||
| @ -30,13 +31,16 @@ import java.io.IOException; | |||||||
|  * |  * | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  */ |  */ | ||||||
| abstract class CommonUsbSerialDriver implements UsbSerialDriver { | abstract class CommonUsbSerialPort implements UsbSerialPort { | ||||||
| 
 | 
 | ||||||
|     public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024; |     public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024; | ||||||
|     public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024; |     public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024; | ||||||
| 
 | 
 | ||||||
|     protected final UsbDevice mDevice; |     protected final UsbDevice mDevice; | ||||||
|     protected final UsbDeviceConnection mConnection; |     protected final int mPortNumber; | ||||||
|  | 
 | ||||||
|  |     // non-null when open() | ||||||
|  |     protected UsbDeviceConnection mConnection = null; | ||||||
| 
 | 
 | ||||||
|     protected final Object mReadBufferLock = new Object(); |     protected final Object mReadBufferLock = new Object(); | ||||||
|     protected final Object mWriteBufferLock = new Object(); |     protected final Object mWriteBufferLock = new Object(); | ||||||
| @ -47,14 +51,21 @@ abstract class CommonUsbSerialDriver implements UsbSerialDriver { | |||||||
|     /** Internal write buffer.  Guarded by {@link #mWriteBufferLock}. */ |     /** Internal write buffer.  Guarded by {@link #mWriteBufferLock}. */ | ||||||
|     protected byte[] mWriteBuffer; |     protected byte[] mWriteBuffer; | ||||||
| 
 | 
 | ||||||
|     public CommonUsbSerialDriver(UsbDevice device, UsbDeviceConnection connection) { |     public CommonUsbSerialPort(UsbDevice device, int portNumber) { | ||||||
|         mDevice = device; |         mDevice = device; | ||||||
|         mConnection = connection; |         mPortNumber = portNumber; | ||||||
| 
 | 
 | ||||||
|         mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE]; |         mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE]; | ||||||
|         mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE]; |         mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE]; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     @Override | ||||||
|  |     public String toString() { | ||||||
|  |         return String.format("<%s device_name=%s device_id=%s port_number=%s>", | ||||||
|  |                 getClass().getSimpleName(), mDevice.getDeviceName(), | ||||||
|  |                 mDevice.getDeviceId(), mPortNumber); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Returns the currently-bound USB device. |      * Returns the currently-bound USB device. | ||||||
|      * |      * | ||||||
| @ -64,6 +75,11 @@ abstract class CommonUsbSerialDriver implements UsbSerialDriver { | |||||||
|         return mDevice; |         return mDevice; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public int getPortNumber() { | ||||||
|  |         return mPortNumber; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Sets the size of the internal buffer used to exchange data with the USB |      * Sets the size of the internal buffer used to exchange data with the USB | ||||||
|      * stack for read operations.  Most users should not need to change this. |      * stack for read operations.  Most users should not need to change this. | ||||||
| @ -95,7 +111,7 @@ abstract class CommonUsbSerialDriver implements UsbSerialDriver { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public abstract void open() throws IOException; |     public abstract void open(UsbDeviceConnection connection) throws IOException; | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public abstract void close() throws IOException; |     public abstract void close() throws IOException; | ||||||
| @ -0,0 +1,360 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/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.util.Log; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | public class Cp21xxSerialDriver implements UsbSerialDriver { | ||||||
|  | 
 | ||||||
|  |     private static final String TAG = Cp21xxSerialDriver.class.getSimpleName(); | ||||||
|  | 
 | ||||||
|  |     private final UsbDevice mDevice; | ||||||
|  |     private final UsbSerialPort mPort; | ||||||
|  | 
 | ||||||
|  |     public Cp21xxSerialDriver(UsbDevice device) { | ||||||
|  |         mDevice = device; | ||||||
|  |         mPort = new Cp21xxSerialPort(mDevice, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UsbDevice getDevice() { | ||||||
|  |         return mDevice; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<UsbSerialPort> getPorts() { | ||||||
|  |         return Collections.singletonList(mPort); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public class Cp21xxSerialPort extends CommonUsbSerialPort { | ||||||
|  | 
 | ||||||
|  |         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; | ||||||
|  |         private static final int SILABSER_FLUSH_REQUEST_CODE = 0x12; | ||||||
|  | 
 | ||||||
|  |        private static final int FLUSH_READ_CODE = 0x0a; | ||||||
|  |        private static final int FLUSH_WRITE_CODE = 0x05; | ||||||
|  | 
 | ||||||
|  |         /* | ||||||
|  |          * 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 Cp21xxSerialPort(UsbDevice device, int portNumber) { | ||||||
|  |             super(device, portNumber); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public UsbSerialDriver getDriver() { | ||||||
|  |             return Cp21xxSerialDriver.this; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         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(UsbDeviceConnection connection) throws IOException { | ||||||
|  |             if (mConnection != null) { | ||||||
|  |                 throw new IOException("Already opened."); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             mConnection = connection; | ||||||
|  |             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) { | ||||||
|  |                     try { | ||||||
|  |                         close(); | ||||||
|  |                     } catch (IOException e) { | ||||||
|  |                         // Ignore IOExceptions during close() | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void close() throws IOException { | ||||||
|  |             if (mConnection == null) { | ||||||
|  |                 throw new IOException("Already closed"); | ||||||
|  |             } | ||||||
|  |             try { | ||||||
|  |                 setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE); | ||||||
|  |                 mConnection.close(); | ||||||
|  |             } finally { | ||||||
|  |                 mConnection = null; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @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; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void setBaudRate(int baudRate) throws IOException { | ||||||
|  |             byte[] data = new byte[] { | ||||||
|  |                     (byte) ( baudRate & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 8 ) & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 16) & 0xff), | ||||||
|  |                     (byte) ((baudRate >> 24) & 0xff) | ||||||
|  |             }; | ||||||
|  |             int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE, | ||||||
|  |                     0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |             if (ret < 0) { | ||||||
|  |                 throw new IOException("Error setting baud rate."); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @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 { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean purgeHwBuffers(boolean purgeReadBuffers, | ||||||
|  |                 boolean purgeWriteBuffers) throws IOException { | ||||||
|  |             int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0) | ||||||
|  |                     | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0); | ||||||
|  | 
 | ||||||
|  |             if (value != 0) { | ||||||
|  |                 setConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Map<Integer, int[]> getSupportedDevices() { | ||||||
|  |         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILABS), | ||||||
|  |                 new int[] { | ||||||
|  |             UsbId.SILABS_CP2102, | ||||||
|  |             UsbId.SILABS_CP2105, | ||||||
|  |             UsbId.SILABS_CP2108, | ||||||
|  |             UsbId.SILABS_CP2110 | ||||||
|  |         }); | ||||||
|  |         return supportedDevices; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,581 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/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.UsbRequest; | ||||||
|  | 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.LinkedHashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A {@link CommonUsbSerialPort} implementation for a variety of FTDI devices | ||||||
|  |  * <p> | ||||||
|  |  * This driver is based on <a | ||||||
|  |  * href="http://www.intra2net.com/en/developer/libftdi">libftdi</a>, and is | ||||||
|  |  * copyright and subject to the following terms: | ||||||
|  |  * | ||||||
|  |  * <pre> | ||||||
|  |  *   Copyright (C) 2003 by Intra2net AG | ||||||
|  |  * | ||||||
|  |  *   This program is free software; you can redistribute it and/or modify | ||||||
|  |  *   it under the terms of the GNU Lesser General Public License | ||||||
|  |  *   version 2.1 as published by the Free Software Foundation; | ||||||
|  |  * | ||||||
|  |  *   opensource@intra2net.com | ||||||
|  |  *   http://www.intra2net.com/en/developer/libftdi | ||||||
|  |  * </pre> | ||||||
|  |  * | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Some FTDI devices have not been tested; see later listing of supported and | ||||||
|  |  * unsupported devices. Devices listed as "supported" support the following | ||||||
|  |  * features: | ||||||
|  |  * <ul> | ||||||
|  |  * <li>Read and write of serial data (see | ||||||
|  |  * {@link CommonUsbSerialPort#read(byte[], int)} and | ||||||
|  |  * {@link CommonUsbSerialPort#write(byte[], int)}.</li> | ||||||
|  |  * <li>Setting serial line parameters (see | ||||||
|  |  * {@link CommonUsbSerialPort#setParameters(int, int, int, int)}.</li> | ||||||
|  |  * </ul> | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Supported and tested devices: | ||||||
|  |  * <ul> | ||||||
|  |  * <li>{@value DeviceType#TYPE_R}</li> | ||||||
|  |  * </ul> | ||||||
|  |  * </p> | ||||||
|  |  * <p> | ||||||
|  |  * Unsupported but possibly working devices (please contact the author with | ||||||
|  |  * 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> | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  |  * @see <a href="https://github.com/mik3y/usb-serial-for-android">USB Serial | ||||||
|  |  *      for Android project page</a> | ||||||
|  |  * @see <a href="http://www.ftdichip.com/">FTDI Homepage</a> | ||||||
|  |  * @see <a href="http://www.intra2net.com/en/developer/libftdi">libftdi</a> | ||||||
|  |  */ | ||||||
|  | public class FtdiSerialDriver implements UsbSerialDriver { | ||||||
|  | 
 | ||||||
|  |     private final UsbDevice mDevice; | ||||||
|  |     private final UsbSerialPort mPort; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * FTDI chip types. | ||||||
|  |      */ | ||||||
|  |     private static enum DeviceType { | ||||||
|  |         TYPE_BM, TYPE_AM, TYPE_2232C, TYPE_R, TYPE_2232H, TYPE_4232H; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public FtdiSerialDriver(UsbDevice device) { | ||||||
|  |         mDevice = device; | ||||||
|  |         mPort = new FtdiSerialPort(mDevice, 0); | ||||||
|  |     } | ||||||
|  |     @Override | ||||||
|  |     public UsbDevice getDevice() { | ||||||
|  |         return mDevice; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<UsbSerialPort> getPorts() { | ||||||
|  |         return Collections.singletonList(mPort); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private class FtdiSerialPort extends CommonUsbSerialPort { | ||||||
|  | 
 | ||||||
|  |         public static final int USB_TYPE_STANDARD = 0x00 << 5; | ||||||
|  |         public static final int USB_TYPE_CLASS = 0x00 << 5; | ||||||
|  |         public static final int USB_TYPE_VENDOR = 0x00 << 5; | ||||||
|  |         public static final int USB_TYPE_RESERVED = 0x00 << 5; | ||||||
|  | 
 | ||||||
|  |         public static final int USB_RECIP_DEVICE = 0x00; | ||||||
|  |         public static final int USB_RECIP_INTERFACE = 0x01; | ||||||
|  |         public static final int USB_RECIP_ENDPOINT = 0x02; | ||||||
|  |         public static final int USB_RECIP_OTHER = 0x03; | ||||||
|  | 
 | ||||||
|  |         public static final int USB_ENDPOINT_IN = 0x80; | ||||||
|  |         public static final int USB_ENDPOINT_OUT = 0x00; | ||||||
|  | 
 | ||||||
|  |         public static final int USB_WRITE_TIMEOUT_MILLIS = 5000; | ||||||
|  |         public static final int USB_READ_TIMEOUT_MILLIS = 5000; | ||||||
|  | 
 | ||||||
|  |         // From ftdi.h | ||||||
|  |         /** | ||||||
|  |          * Reset the port. | ||||||
|  |          */ | ||||||
|  |         private static final int SIO_RESET_REQUEST = 0; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Set the modem control register. | ||||||
|  |          */ | ||||||
|  |         private static final int SIO_MODEM_CTRL_REQUEST = 1; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Set flow control register. | ||||||
|  |          */ | ||||||
|  |         private static final int SIO_SET_FLOW_CTRL_REQUEST = 2; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Set baud rate. | ||||||
|  |          */ | ||||||
|  |         private static final int SIO_SET_BAUD_RATE_REQUEST = 3; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Set the data characteristics of the port. | ||||||
|  |          */ | ||||||
|  |         private static final int SIO_SET_DATA_REQUEST = 4; | ||||||
|  | 
 | ||||||
|  |         private static final int SIO_RESET_SIO = 0; | ||||||
|  |         private static final int SIO_RESET_PURGE_RX = 1; | ||||||
|  |         private static final int SIO_RESET_PURGE_TX = 2; | ||||||
|  | 
 | ||||||
|  |         public static final int FTDI_DEVICE_OUT_REQTYPE = | ||||||
|  |                 UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT; | ||||||
|  | 
 | ||||||
|  |         public static final int FTDI_DEVICE_IN_REQTYPE = | ||||||
|  |                 UsbConstants.USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN; | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Length of the modem status header, transmitted with every read. | ||||||
|  |          */ | ||||||
|  |         private static final int MODEM_STATUS_HEADER_LENGTH = 2; | ||||||
|  | 
 | ||||||
|  |         private final String TAG = FtdiSerialDriver.class.getSimpleName(); | ||||||
|  | 
 | ||||||
|  |         private DeviceType mType; | ||||||
|  | 
 | ||||||
|  |         private int mInterface = 0; /* INTERFACE_ANY */ | ||||||
|  | 
 | ||||||
|  |         private int mMaxPacketSize = 64; // TODO(mikey): detect | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * 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. | ||||||
|  |          */ | ||||||
|  |         private static final boolean ENABLE_ASYNC_READS = false; | ||||||
|  | 
 | ||||||
|  |         public FtdiSerialPort(UsbDevice device, int portNumber) { | ||||||
|  |             super(device, portNumber); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public UsbSerialDriver getDriver() { | ||||||
|  |             return FtdiSerialDriver.this; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /** | ||||||
|  |          * Filter FTDI status bytes from buffer | ||||||
|  |          * @param src The source buffer (which contains status bytes) | ||||||
|  |          * @param dest The destination buffer to write the status bytes into (can be src) | ||||||
|  |          * @param totalBytesRead Number of bytes read to src | ||||||
|  |          * @param maxPacketSize The USB endpoint max packet size | ||||||
|  |          * @return The number of payload bytes | ||||||
|  |          */ | ||||||
|  |         private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) { | ||||||
|  |             final int packetsCount = totalBytesRead / maxPacketSize + 1; | ||||||
|  |             for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) { | ||||||
|  |                 final int count = (packetIdx == (packetsCount - 1)) | ||||||
|  |                         ? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH | ||||||
|  |                         : maxPacketSize - MODEM_STATUS_HEADER_LENGTH; | ||||||
|  |                 if (count > 0) { | ||||||
|  |                     System.arraycopy(src, | ||||||
|  |                             packetIdx * maxPacketSize + MODEM_STATUS_HEADER_LENGTH, | ||||||
|  |                             dest, | ||||||
|  |                             packetIdx * (maxPacketSize - MODEM_STATUS_HEADER_LENGTH), | ||||||
|  |                             count); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |           return totalBytesRead - (packetsCount * 2); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void reset() throws IOException { | ||||||
|  |             int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST, | ||||||
|  |                     SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |             if (result != 0) { | ||||||
|  |                 throw new IOException("Reset failed: result=" + result); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // TODO(mikey): autodetect. | ||||||
|  |             mType = DeviceType.TYPE_R; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void open(UsbDeviceConnection connection) throws IOException { | ||||||
|  |             if (mConnection != null) { | ||||||
|  |                 throw new IOException("Already open"); | ||||||
|  |             } | ||||||
|  |             mConnection = connection; | ||||||
|  | 
 | ||||||
|  |             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); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 reset(); | ||||||
|  |                 opened = true; | ||||||
|  |             } finally { | ||||||
|  |                 if (!opened) { | ||||||
|  |                     close(); | ||||||
|  |                     mConnection = null; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void close() throws IOException { | ||||||
|  |             if (mConnection == null) { | ||||||
|  |                 throw new IOException("Already closed"); | ||||||
|  |             } | ||||||
|  |             try { | ||||||
|  |                 mConnection.close(); | ||||||
|  |             } finally { | ||||||
|  |                 mConnection = null; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||||
|  |             final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(0); | ||||||
|  | 
 | ||||||
|  |             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, endpoint); | ||||||
|  | 
 | ||||||
|  |                 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 payloadBytesRead = buf.position() - MODEM_STATUS_HEADER_LENGTH; | ||||||
|  |                 if (payloadBytesRead > 0) { | ||||||
|  |                     Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length))); | ||||||
|  |                     return payloadBytesRead; | ||||||
|  |                 } else { | ||||||
|  |                     return 0; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 final int totalBytesRead; | ||||||
|  | 
 | ||||||
|  |                 synchronized (mReadBufferLock) { | ||||||
|  |                     final int readAmt = Math.min(dest.length, mReadBuffer.length); | ||||||
|  |                     totalBytesRead = mConnection.bulkTransfer(endpoint, mReadBuffer, | ||||||
|  |                             readAmt, timeoutMillis); | ||||||
|  | 
 | ||||||
|  |                     if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) { | ||||||
|  |                         throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes"); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     return filterStatusBytes(mReadBuffer, dest, totalBytesRead, endpoint.getMaxPacketSize()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int write(byte[] src, int timeoutMillis) throws IOException { | ||||||
|  |             final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1); | ||||||
|  |             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(endpoint, 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; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private int setBaudRate(int baudRate) throws IOException { | ||||||
|  |             long[] vals = convertBaudrate(baudRate); | ||||||
|  |             long actualBaudrate = vals[0]; | ||||||
|  |             long index = vals[1]; | ||||||
|  |             long value = vals[2]; | ||||||
|  |             int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, | ||||||
|  |                     SIO_SET_BAUD_RATE_REQUEST, (int) value, (int) index, | ||||||
|  |                     null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |             if (result != 0) { | ||||||
|  |                 throw new IOException("Setting baudrate failed: result=" + result); | ||||||
|  |             } | ||||||
|  |             return (int) actualBaudrate; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setParameters(int baudRate, int dataBits, int stopBits, int parity) | ||||||
|  |                 throws IOException { | ||||||
|  |             setBaudRate(baudRate); | ||||||
|  | 
 | ||||||
|  |             int config = dataBits; | ||||||
|  | 
 | ||||||
|  |             switch (parity) { | ||||||
|  |                 case PARITY_NONE: | ||||||
|  |                     config |= (0x00 << 8); | ||||||
|  |                     break; | ||||||
|  |                 case PARITY_ODD: | ||||||
|  |                     config |= (0x01 << 8); | ||||||
|  |                     break; | ||||||
|  |                 case PARITY_EVEN: | ||||||
|  |                     config |= (0x02 << 8); | ||||||
|  |                     break; | ||||||
|  |                 case PARITY_MARK: | ||||||
|  |                     config |= (0x03 << 8); | ||||||
|  |                     break; | ||||||
|  |                 case PARITY_SPACE: | ||||||
|  |                     config |= (0x04 << 8); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     throw new IllegalArgumentException("Unknown parity value: " + parity); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             switch (stopBits) { | ||||||
|  |                 case STOPBITS_1: | ||||||
|  |                     config |= (0x00 << 11); | ||||||
|  |                     break; | ||||||
|  |                 case STOPBITS_1_5: | ||||||
|  |                     config |= (0x01 << 11); | ||||||
|  |                     break; | ||||||
|  |                 case STOPBITS_2: | ||||||
|  |                     config |= (0x02 << 11); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, | ||||||
|  |                     SIO_SET_DATA_REQUEST, config, 0 /* index */, | ||||||
|  |                     null, 0, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |             if (result != 0) { | ||||||
|  |                 throw new IOException("Setting parameters failed: result=" + result); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private long[] convertBaudrate(int baudrate) { | ||||||
|  |             // TODO(mikey): Braindead transcription of libfti method.  Clean up, | ||||||
|  |             // using more idiomatic Java where possible. | ||||||
|  |             int divisor = 24000000 / baudrate; | ||||||
|  |             int bestDivisor = 0; | ||||||
|  |             int bestBaud = 0; | ||||||
|  |             int bestBaudDiff = 0; | ||||||
|  |             int fracCode[] = { | ||||||
|  |                     0, 3, 2, 4, 1, 5, 6, 7 | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             for (int i = 0; i < 2; i++) { | ||||||
|  |                 int tryDivisor = divisor + i; | ||||||
|  |                 int baudEstimate; | ||||||
|  |                 int baudDiff; | ||||||
|  | 
 | ||||||
|  |                 if (tryDivisor <= 8) { | ||||||
|  |                     // Round up to minimum supported divisor | ||||||
|  |                     tryDivisor = 8; | ||||||
|  |                 } else if (mType != DeviceType.TYPE_AM && tryDivisor < 12) { | ||||||
|  |                     // BM doesn't support divisors 9 through 11 inclusive | ||||||
|  |                     tryDivisor = 12; | ||||||
|  |                 } else if (divisor < 16) { | ||||||
|  |                     // AM doesn't support divisors 9 through 15 inclusive | ||||||
|  |                     tryDivisor = 16; | ||||||
|  |                 } else { | ||||||
|  |                     if (mType == DeviceType.TYPE_AM) { | ||||||
|  |                         // TODO | ||||||
|  |                     } else { | ||||||
|  |                         if (tryDivisor > 0x1FFFF) { | ||||||
|  |                             // Round down to maximum supported divisor value (for | ||||||
|  |                             // BM) | ||||||
|  |                             tryDivisor = 0x1FFFF; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 // Get estimated baud rate (to nearest integer) | ||||||
|  |                 baudEstimate = (24000000 + (tryDivisor / 2)) / tryDivisor; | ||||||
|  | 
 | ||||||
|  |                 // Get absolute difference from requested baud rate | ||||||
|  |                 if (baudEstimate < baudrate) { | ||||||
|  |                     baudDiff = baudrate - baudEstimate; | ||||||
|  |                 } else { | ||||||
|  |                     baudDiff = baudEstimate - baudrate; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (i == 0 || baudDiff < bestBaudDiff) { | ||||||
|  |                     // Closest to requested baud rate so far | ||||||
|  |                     bestDivisor = tryDivisor; | ||||||
|  |                     bestBaud = baudEstimate; | ||||||
|  |                     bestBaudDiff = baudDiff; | ||||||
|  |                     if (baudDiff == 0) { | ||||||
|  |                         // Spot on! No point trying | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Encode the best divisor value | ||||||
|  |             long encodedDivisor = (bestDivisor >> 3) | (fracCode[bestDivisor & 7] << 14); | ||||||
|  |             // Deal with special cases for encoded value | ||||||
|  |             if (encodedDivisor == 1) { | ||||||
|  |                 encodedDivisor = 0; // 3000000 baud | ||||||
|  |             } else if (encodedDivisor == 0x4001) { | ||||||
|  |                 encodedDivisor = 1; // 2000000 baud (BM only) | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Split into "value" and "index" values | ||||||
|  |             long value = encodedDivisor & 0xFFFF; | ||||||
|  |             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 */; | ||||||
|  |             } else { | ||||||
|  |                 index = (encodedDivisor >> 16) & 0xffff; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Return the nearest baud rate | ||||||
|  |             return new long[] { | ||||||
|  |                     bestBaud, index, value | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @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 false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setDTR(boolean value) throws IOException { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRI() throws IOException { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRTS() throws IOException { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setRTS(boolean value) throws IOException { | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         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); | ||||||
|  |                 if (result != 0) { | ||||||
|  |                     throw new IOException("Flushing RX failed: result=" + result); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             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); | ||||||
|  |                 if (result != 0) { | ||||||
|  |                     throw new IOException("Flushing RX failed: result=" + result); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Map<Integer, int[]> getSupportedDevices() { | ||||||
|  |         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI), | ||||||
|  |                 new int[] { | ||||||
|  |                     UsbId.FTDI_FT232R, | ||||||
|  |                     UsbId.FTDI_FT231X, | ||||||
|  |                 }); | ||||||
|  |         return supportedDevices; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,108 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/usb-serial-for-android | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package com.hoho.android.usbserial.driver; | ||||||
|  | 
 | ||||||
|  | import android.util.Pair; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Maps (vendor id, product id) pairs to the corresponding serial driver. | ||||||
|  |  * | ||||||
|  |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  |  */ | ||||||
|  | public class ProbeTable { | ||||||
|  | 
 | ||||||
|  |     private final Map<Pair<Integer, Integer>, Class<? extends UsbSerialDriver>> mProbeTable = | ||||||
|  |             new LinkedHashMap<Pair<Integer,Integer>, Class<? extends UsbSerialDriver>>(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds or updates a (vendor, product) pair in the table. | ||||||
|  |      * | ||||||
|  |      * @param vendorId the USB vendor id | ||||||
|  |      * @param productId the USB product id | ||||||
|  |      * @param driverClass the driver class responsible for this pair | ||||||
|  |      * @return {@code this}, for chaining | ||||||
|  |      */ | ||||||
|  |     public ProbeTable addProduct(int vendorId, int productId, | ||||||
|  |             Class<? extends UsbSerialDriver> driverClass) { | ||||||
|  |         mProbeTable.put(Pair.create(vendorId, productId), driverClass); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Internal method to add all supported products from | ||||||
|  |      * {@code getSupportedProducts} static method. | ||||||
|  |      * | ||||||
|  |      * @param driverClass | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     @SuppressWarnings("unchecked") | ||||||
|  |     ProbeTable addDriver(Class<? extends UsbSerialDriver> driverClass) { | ||||||
|  |         final Method method; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             method = driverClass.getMethod("getSupportedDevices"); | ||||||
|  |         } catch (SecurityException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } catch (NoSuchMethodException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         final Map<Integer, int[]> devices; | ||||||
|  |         try { | ||||||
|  |             devices = (Map<Integer, int[]>) method.invoke(null); | ||||||
|  |         } catch (IllegalArgumentException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } catch (IllegalAccessException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } catch (InvocationTargetException e) { | ||||||
|  |             throw new RuntimeException(e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (Map.Entry<Integer, int[]> entry : devices.entrySet()) { | ||||||
|  |             final int vendorId = entry.getKey().intValue(); | ||||||
|  |             for (int productId : entry.getValue()) { | ||||||
|  |                 addProduct(vendorId, productId, driverClass); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the driver for the given (vendor, product) pair, or {@code null} | ||||||
|  |      * if no match. | ||||||
|  |      * | ||||||
|  |      * @param vendorId the USB vendor id | ||||||
|  |      * @param productId the USB product id | ||||||
|  |      * @return the driver class matching this pair, or {@code null} | ||||||
|  |      */ | ||||||
|  |     public Class<? extends UsbSerialDriver> findDriver(int vendorId, int productId) { | ||||||
|  |         final Pair<Integer, Integer> pair = Pair.create(vendorId, productId); | ||||||
|  |         return mProbeTable.get(pair); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,556 @@ | |||||||
|  | /* 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: https://github.com/mik3y/usb-serial-for-android | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * Ported to usb-serial-for-android | ||||||
|  |  * by Felix Hädicke <felixhaedicke@web.de> | ||||||
|  |  * | ||||||
|  |  * Based on the pyprolific driver written | ||||||
|  |  * by Emmanuel Blot <emmanuel.blot@free.fr> | ||||||
|  |  * See https://github.com/eblot/pyftdi | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 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.util.Log; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.lang.reflect.Method; | ||||||
|  | import java.util.Collections; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | 
 | ||||||
|  | public class ProlificSerialDriver implements UsbSerialDriver { | ||||||
|  | 
 | ||||||
|  |     private final String TAG = ProlificSerialDriver.class.getSimpleName(); | ||||||
|  | 
 | ||||||
|  |     private final UsbDevice mDevice; | ||||||
|  |     private final UsbSerialPort mPort; | ||||||
|  | 
 | ||||||
|  |     public ProlificSerialDriver(UsbDevice device) { | ||||||
|  |         mDevice = device; | ||||||
|  |         mPort = new ProlificSerialPort(mDevice, 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public List<UsbSerialPort> getPorts() { | ||||||
|  |         return Collections.singletonList(mPort); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public UsbDevice getDevice() { | ||||||
|  |         return mDevice; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     class ProlificSerialPort extends CommonUsbSerialPort { | ||||||
|  | 
 | ||||||
|  |         private static final int USB_READ_TIMEOUT_MILLIS = 1000; | ||||||
|  |         private static final int USB_WRITE_TIMEOUT_MILLIS = 5000; | ||||||
|  | 
 | ||||||
|  |         private static final int USB_RECIP_INTERFACE = 0x01; | ||||||
|  | 
 | ||||||
|  |         private static final int PROLIFIC_VENDOR_READ_REQUEST = 0x01; | ||||||
|  |         private static final int PROLIFIC_VENDOR_WRITE_REQUEST = 0x01; | ||||||
|  | 
 | ||||||
|  |         private static final int PROLIFIC_VENDOR_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | ||||||
|  |                 | UsbConstants.USB_TYPE_VENDOR; | ||||||
|  | 
 | ||||||
|  |         private static final int PROLIFIC_VENDOR_IN_REQTYPE = UsbConstants.USB_DIR_IN | ||||||
|  |                 | UsbConstants.USB_TYPE_VENDOR; | ||||||
|  | 
 | ||||||
|  |         private static final int PROLIFIC_CTRL_OUT_REQTYPE = UsbConstants.USB_DIR_OUT | ||||||
|  |                 | UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||||||
|  | 
 | ||||||
|  |         private static final int WRITE_ENDPOINT = 0x02; | ||||||
|  |         private static final int READ_ENDPOINT = 0x83; | ||||||
|  |         private static final int INTERRUPT_ENDPOINT = 0x81; | ||||||
|  | 
 | ||||||
|  |         private static final int FLUSH_RX_REQUEST = 0x08; | ||||||
|  |         private static final int FLUSH_TX_REQUEST = 0x09; | ||||||
|  | 
 | ||||||
|  |         private static final int SET_LINE_REQUEST = 0x20; | ||||||
|  |         private static final int SET_CONTROL_REQUEST = 0x22; | ||||||
|  | 
 | ||||||
|  |         private static final int CONTROL_DTR = 0x01; | ||||||
|  |         private static final int CONTROL_RTS = 0x02; | ||||||
|  | 
 | ||||||
|  |         private static final int STATUS_FLAG_CD = 0x01; | ||||||
|  |         private static final int STATUS_FLAG_DSR = 0x02; | ||||||
|  |         private static final int STATUS_FLAG_RI = 0x08; | ||||||
|  |         private static final int STATUS_FLAG_CTS = 0x80; | ||||||
|  | 
 | ||||||
|  |         private static final int STATUS_BUFFER_SIZE = 10; | ||||||
|  |         private static final int STATUS_BYTE_IDX = 8; | ||||||
|  | 
 | ||||||
|  |         private static final int DEVICE_TYPE_HX = 0; | ||||||
|  |         private static final int DEVICE_TYPE_0 = 1; | ||||||
|  |         private static final int DEVICE_TYPE_1 = 2; | ||||||
|  | 
 | ||||||
|  |         private int mDeviceType = DEVICE_TYPE_HX; | ||||||
|  | 
 | ||||||
|  |         private UsbEndpoint mReadEndpoint; | ||||||
|  |         private UsbEndpoint mWriteEndpoint; | ||||||
|  |         private UsbEndpoint mInterruptEndpoint; | ||||||
|  | 
 | ||||||
|  |         private int mControlLinesValue = 0; | ||||||
|  | 
 | ||||||
|  |         private int mBaudRate = -1, mDataBits = -1, mStopBits = -1, mParity = -1; | ||||||
|  | 
 | ||||||
|  |         private int mStatus = 0; | ||||||
|  |         private volatile Thread mReadStatusThread = null; | ||||||
|  |         private final Object mReadStatusThreadLock = new Object(); | ||||||
|  |         boolean mStopReadStatusThread = false; | ||||||
|  |         private IOException mReadStatusException = null; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         public ProlificSerialPort(UsbDevice device, int portNumber) { | ||||||
|  |             super(device, portNumber); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public UsbSerialDriver getDriver() { | ||||||
|  |             return ProlificSerialDriver.this; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final byte[] inControlTransfer(int requestType, int request, | ||||||
|  |                 int value, int index, int length) throws IOException { | ||||||
|  |             byte[] buffer = new byte[length]; | ||||||
|  |             int result = mConnection.controlTransfer(requestType, request, value, | ||||||
|  |                     index, buffer, length, USB_READ_TIMEOUT_MILLIS); | ||||||
|  |             if (result != length) { | ||||||
|  |                 throw new IOException( | ||||||
|  |                         String.format("ControlTransfer with value 0x%x failed: %d", | ||||||
|  |                                 value, result)); | ||||||
|  |             } | ||||||
|  |             return buffer; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final void outControlTransfer(int requestType, int request, | ||||||
|  |                 int value, int index, byte[] data) throws IOException { | ||||||
|  |             int length = (data == null) ? 0 : data.length; | ||||||
|  |             int result = mConnection.controlTransfer(requestType, request, value, | ||||||
|  |                     index, data, length, USB_WRITE_TIMEOUT_MILLIS); | ||||||
|  |             if (result != length) { | ||||||
|  |                 throw new IOException( | ||||||
|  |                         String.format("ControlTransfer with value 0x%x failed: %d", | ||||||
|  |                                 value, result)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final byte[] vendorIn(int value, int index, int length) | ||||||
|  |                 throws IOException { | ||||||
|  |             return inControlTransfer(PROLIFIC_VENDOR_IN_REQTYPE, | ||||||
|  |                     PROLIFIC_VENDOR_READ_REQUEST, value, index, length); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final void vendorOut(int value, int index, byte[] data) | ||||||
|  |                 throws IOException { | ||||||
|  |             outControlTransfer(PROLIFIC_VENDOR_OUT_REQTYPE, | ||||||
|  |                     PROLIFIC_VENDOR_WRITE_REQUEST, value, index, data); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void resetDevice() throws IOException { | ||||||
|  |             purgeHwBuffers(true, true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final void ctrlOut(int request, int value, int index, byte[] data) | ||||||
|  |                 throws IOException { | ||||||
|  |             outControlTransfer(PROLIFIC_CTRL_OUT_REQTYPE, request, value, index, | ||||||
|  |                     data); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void doBlackMagic() throws IOException { | ||||||
|  |             vendorIn(0x8484, 0, 1); | ||||||
|  |             vendorOut(0x0404, 0, null); | ||||||
|  |             vendorIn(0x8484, 0, 1); | ||||||
|  |             vendorIn(0x8383, 0, 1); | ||||||
|  |             vendorIn(0x8484, 0, 1); | ||||||
|  |             vendorOut(0x0404, 1, null); | ||||||
|  |             vendorIn(0x8484, 0, 1); | ||||||
|  |             vendorIn(0x8383, 0, 1); | ||||||
|  |             vendorOut(0, 1, null); | ||||||
|  |             vendorOut(1, 0, null); | ||||||
|  |             vendorOut(2, (mDeviceType == DEVICE_TYPE_HX) ? 0x44 : 0x24, null); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void setControlLines(int newControlLinesValue) throws IOException { | ||||||
|  |             ctrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null); | ||||||
|  |             mControlLinesValue = newControlLinesValue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final void readStatusThreadFunction() { | ||||||
|  |             try { | ||||||
|  |                 while (!mStopReadStatusThread) { | ||||||
|  |                     byte[] buffer = new byte[STATUS_BUFFER_SIZE]; | ||||||
|  |                     int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint, | ||||||
|  |                             buffer, | ||||||
|  |                             STATUS_BUFFER_SIZE, | ||||||
|  |                             500); | ||||||
|  |                     if (readBytesCount > 0) { | ||||||
|  |                         if (readBytesCount == STATUS_BUFFER_SIZE) { | ||||||
|  |                             mStatus = buffer[STATUS_BYTE_IDX] & 0xff; | ||||||
|  |                         } else { | ||||||
|  |                             throw new IOException( | ||||||
|  |                                     String.format("Invalid CTS / DSR / CD / RI status buffer received, expected %d bytes, but received %d", | ||||||
|  |                                             STATUS_BUFFER_SIZE, | ||||||
|  |                                             readBytesCount)); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } catch (IOException e) { | ||||||
|  |                 mReadStatusException = e; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final int getStatus() throws IOException { | ||||||
|  |             if ((mReadStatusThread == null) && (mReadStatusException == null)) { | ||||||
|  |                 synchronized (mReadStatusThreadLock) { | ||||||
|  |                     if (mReadStatusThread == null) { | ||||||
|  |                         byte[] buffer = new byte[STATUS_BUFFER_SIZE]; | ||||||
|  |                         int readBytes = mConnection.bulkTransfer(mInterruptEndpoint, | ||||||
|  |                                 buffer, | ||||||
|  |                                 STATUS_BUFFER_SIZE, | ||||||
|  |                                 100); | ||||||
|  |                         if (readBytes != STATUS_BUFFER_SIZE) { | ||||||
|  |                             Log.w(TAG, "Could not read initial CTS / DSR / CD / RI status"); | ||||||
|  |                         } else { | ||||||
|  |                             mStatus = buffer[STATUS_BYTE_IDX] & 0xff; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         mReadStatusThread = new Thread(new Runnable() { | ||||||
|  |                             @Override | ||||||
|  |                             public void run() { | ||||||
|  |                                 readStatusThreadFunction(); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                         mReadStatusThread.setDaemon(true); | ||||||
|  |                         mReadStatusThread.start(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /* throw and clear an exception which occured in the status read thread */ | ||||||
|  |             IOException readStatusException = mReadStatusException; | ||||||
|  |             if (mReadStatusException != null) { | ||||||
|  |                 mReadStatusException = null; | ||||||
|  |                 throw readStatusException; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return mStatus; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private final boolean testStatusFlag(int flag) throws IOException { | ||||||
|  |             return ((getStatus() & flag) == flag); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void open(UsbDeviceConnection connection) throws IOException { | ||||||
|  |             if (mConnection != null) { | ||||||
|  |                 throw new IOException("Already open"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             UsbInterface usbInterface = mDevice.getInterface(0); | ||||||
|  | 
 | ||||||
|  |             if (!connection.claimInterface(usbInterface, true)) { | ||||||
|  |                 throw new IOException("Error claiming Prolific interface 0"); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             mConnection = connection; | ||||||
|  |             boolean opened = false; | ||||||
|  |             try { | ||||||
|  |                 for (int i = 0; i < usbInterface.getEndpointCount(); ++i) { | ||||||
|  |                     UsbEndpoint currentEndpoint = usbInterface.getEndpoint(i); | ||||||
|  | 
 | ||||||
|  |                     switch (currentEndpoint.getAddress()) { | ||||||
|  |                     case READ_ENDPOINT: | ||||||
|  |                         mReadEndpoint = currentEndpoint; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     case WRITE_ENDPOINT: | ||||||
|  |                         mWriteEndpoint = currentEndpoint; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     case INTERRUPT_ENDPOINT: | ||||||
|  |                         mInterruptEndpoint = currentEndpoint; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (mDevice.getDeviceClass() == 0x02) { | ||||||
|  |                     mDeviceType = DEVICE_TYPE_0; | ||||||
|  |                 } else { | ||||||
|  |                     try { | ||||||
|  |                         Method getRawDescriptorsMethod | ||||||
|  |                             = mConnection.getClass().getMethod("getRawDescriptors"); | ||||||
|  |                         byte[] rawDescriptors | ||||||
|  |                             = (byte[]) getRawDescriptorsMethod.invoke(mConnection); | ||||||
|  |                         byte maxPacketSize0 = rawDescriptors[7]; | ||||||
|  |                         if (maxPacketSize0 == 64) { | ||||||
|  |                             mDeviceType = DEVICE_TYPE_HX; | ||||||
|  |                         } else if ((mDevice.getDeviceClass() == 0x00) | ||||||
|  |                                 || (mDevice.getDeviceClass() == 0xff)) { | ||||||
|  |                             mDeviceType = DEVICE_TYPE_1; | ||||||
|  |                         } else { | ||||||
|  |                           Log.w(TAG, "Could not detect PL2303 subtype, " | ||||||
|  |                               + "Assuming that it is a HX device"); | ||||||
|  |                           mDeviceType = DEVICE_TYPE_HX; | ||||||
|  |                         } | ||||||
|  |                     } catch (NoSuchMethodException e) { | ||||||
|  |                         Log.w(TAG, "Method UsbDeviceConnection.getRawDescriptors, " | ||||||
|  |                                 + "required for PL2303 subtype detection, not " | ||||||
|  |                                 + "available! Assuming that it is a HX device"); | ||||||
|  |                         mDeviceType = DEVICE_TYPE_HX; | ||||||
|  |                     } catch (Exception e) { | ||||||
|  |                         Log.e(TAG, "An unexpected exception occured while trying " | ||||||
|  |                                 + "to detect PL2303 subtype", e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 setControlLines(mControlLinesValue); | ||||||
|  |                 resetDevice(); | ||||||
|  | 
 | ||||||
|  |                 doBlackMagic(); | ||||||
|  |                 opened = true; | ||||||
|  |             } finally { | ||||||
|  |                 if (!opened) { | ||||||
|  |                     mConnection = null; | ||||||
|  |                     connection.releaseInterface(usbInterface); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void close() throws IOException { | ||||||
|  |             if (mConnection == null) { | ||||||
|  |                 throw new IOException("Already closed"); | ||||||
|  |             } | ||||||
|  |             try { | ||||||
|  |                 mStopReadStatusThread = true; | ||||||
|  |                 synchronized (mReadStatusThreadLock) { | ||||||
|  |                     if (mReadStatusThread != null) { | ||||||
|  |                         try { | ||||||
|  |                             mReadStatusThread.join(); | ||||||
|  |                         } catch (Exception e) { | ||||||
|  |                             Log.w(TAG, "An error occured while waiting for status read thread", e); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 resetDevice(); | ||||||
|  |             } finally { | ||||||
|  |                 try { | ||||||
|  |                     mConnection.releaseInterface(mDevice.getInterface(0)); | ||||||
|  |                 } finally { | ||||||
|  |                     mConnection = null; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public int read(byte[] dest, int timeoutMillis) throws IOException { | ||||||
|  |             synchronized (mReadBufferLock) { | ||||||
|  |                 int readAmt = Math.min(dest.length, mReadBuffer.length); | ||||||
|  |                 int numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, | ||||||
|  |                         readAmt, timeoutMillis); | ||||||
|  |                 if (numBytesRead < 0) { | ||||||
|  |                     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); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 offset += amtWritten; | ||||||
|  |             } | ||||||
|  |             return offset; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setParameters(int baudRate, int dataBits, int stopBits, | ||||||
|  |                 int parity) throws IOException { | ||||||
|  |             if ((mBaudRate == baudRate) && (mDataBits == dataBits) | ||||||
|  |                     && (mStopBits == stopBits) && (mParity == parity)) { | ||||||
|  |                 // Make sure no action is performed if there is nothing to change | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             byte[] lineRequestData = new byte[7]; | ||||||
|  | 
 | ||||||
|  |             lineRequestData[0] = (byte) (baudRate & 0xff); | ||||||
|  |             lineRequestData[1] = (byte) ((baudRate >> 8) & 0xff); | ||||||
|  |             lineRequestData[2] = (byte) ((baudRate >> 16) & 0xff); | ||||||
|  |             lineRequestData[3] = (byte) ((baudRate >> 24) & 0xff); | ||||||
|  | 
 | ||||||
|  |             switch (stopBits) { | ||||||
|  |             case STOPBITS_1: | ||||||
|  |                 lineRequestData[4] = 0; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             case STOPBITS_1_5: | ||||||
|  |                 lineRequestData[4] = 1; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             case STOPBITS_2: | ||||||
|  |                 lineRequestData[4] = 2; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             default: | ||||||
|  |                 throw new IllegalArgumentException("Unknown stopBits value: " + stopBits); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             switch (parity) { | ||||||
|  |             case PARITY_NONE: | ||||||
|  |                 lineRequestData[5] = 0; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             case PARITY_ODD: | ||||||
|  |                 lineRequestData[5] = 1; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             case PARITY_MARK: | ||||||
|  |                 lineRequestData[5] = 3; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             case PARITY_SPACE: | ||||||
|  |                 lineRequestData[5] = 4; | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             default: | ||||||
|  |                 throw new IllegalArgumentException("Unknown parity value: " + parity); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             lineRequestData[6] = (byte) dataBits; | ||||||
|  | 
 | ||||||
|  |             ctrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData); | ||||||
|  | 
 | ||||||
|  |             resetDevice(); | ||||||
|  | 
 | ||||||
|  |             mBaudRate = baudRate; | ||||||
|  |             mDataBits = dataBits; | ||||||
|  |             mStopBits = stopBits; | ||||||
|  |             mParity = parity; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getCD() throws IOException { | ||||||
|  |             return testStatusFlag(STATUS_FLAG_CD); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getCTS() throws IOException { | ||||||
|  |             return testStatusFlag(STATUS_FLAG_CTS); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getDSR() throws IOException { | ||||||
|  |             return testStatusFlag(STATUS_FLAG_DSR); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getDTR() throws IOException { | ||||||
|  |             return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setDTR(boolean value) throws IOException { | ||||||
|  |             int newControlLinesValue; | ||||||
|  |             if (value) { | ||||||
|  |                 newControlLinesValue = mControlLinesValue | CONTROL_DTR; | ||||||
|  |             } else { | ||||||
|  |                 newControlLinesValue = mControlLinesValue & ~CONTROL_DTR; | ||||||
|  |             } | ||||||
|  |             setControlLines(newControlLinesValue); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRI() throws IOException { | ||||||
|  |             return testStatusFlag(STATUS_FLAG_RI); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean getRTS() throws IOException { | ||||||
|  |             return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public void setRTS(boolean value) throws IOException { | ||||||
|  |             int newControlLinesValue; | ||||||
|  |             if (value) { | ||||||
|  |                 newControlLinesValue = mControlLinesValue | CONTROL_RTS; | ||||||
|  |             } else { | ||||||
|  |                 newControlLinesValue = mControlLinesValue & ~CONTROL_RTS; | ||||||
|  |             } | ||||||
|  |             setControlLines(newControlLinesValue); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException { | ||||||
|  |             if (purgeReadBuffers) { | ||||||
|  |                 vendorOut(FLUSH_RX_REQUEST, 0, null); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (purgeWriteBuffers) { | ||||||
|  |                 vendorOut(FLUSH_TX_REQUEST, 0, null); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return purgeReadBuffers || purgeWriteBuffers; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Map<Integer, int[]> getSupportedDevices() { | ||||||
|  |         final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); | ||||||
|  |         supportedDevices.put(Integer.valueOf(UsbId.VENDOR_PROLIFIC), | ||||||
|  |                 new int[] { UsbId.PROLIFIC_PL2303, }); | ||||||
|  |         return supportedDevices; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2012 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,8 +16,9 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
|  | 
 | ||||||
| package com.hoho.android.usbserial.driver; | package com.hoho.android.usbserial.driver; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -53,8 +55,11 @@ 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 VENDOR_SILABS = 0x10c4; | ||||||
|     public static final int SILAB_CP2102 = 0xea60; |     public static final int SILABS_CP2102 = 0xea60; | ||||||
|  |     public static final int SILABS_CP2105 = 0xea70; | ||||||
|  |     public static final int SILABS_CP2108 = 0xea71; | ||||||
|  |     public static final int SILABS_CP2110 = 0xea80; | ||||||
| 
 | 
 | ||||||
|     public static final int VENDOR_PROLIFIC = 0x067b; |     public static final int VENDOR_PROLIFIC = 0x067b; | ||||||
|     public static final int PROLIFIC_PL2303 = 0x2303; |     public static final int PROLIFIC_PL2303 = 0x2303; | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/usb-serial-for-android | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package com.hoho.android.usbserial.driver; | ||||||
|  | 
 | ||||||
|  | import android.hardware.usb.UsbDevice; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  |  */ | ||||||
|  | public interface UsbSerialDriver { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the raw {@link UsbDevice} backing this port. | ||||||
|  |      * | ||||||
|  |      * @return the device | ||||||
|  |      */ | ||||||
|  |     public UsbDevice getDevice(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns all available ports for this device. This list must have at least | ||||||
|  |      * one entry. | ||||||
|  |      * | ||||||
|  |      * @return the ports | ||||||
|  |      */ | ||||||
|  |     public List<UsbSerialPort> getPorts(); | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2011 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,19 +16,22 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.hoho.android.usbserial.driver; | package com.hoho.android.usbserial.driver; | ||||||
| 
 | 
 | ||||||
|  | import android.hardware.usb.UsbDeviceConnection; | ||||||
|  | import android.hardware.usb.UsbManager; | ||||||
|  | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Driver interface for a USB serial device. |  * Interface for a single serial port. | ||||||
|  * |  * | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  */ |  */ | ||||||
| public interface UsbSerialDriver { | public interface UsbSerialPort { | ||||||
| 
 | 
 | ||||||
|     /** 5 data bits. */ |     /** 5 data bits. */ | ||||||
|     public static final int DATABITS_5 = 5; |     public static final int DATABITS_5 = 5; | ||||||
| @ -80,18 +84,27 @@ public interface UsbSerialDriver { | |||||||
|     /** 2 stop bits. */ |     /** 2 stop bits. */ | ||||||
|     public static final int STOPBITS_2 = 2; |     public static final int STOPBITS_2 = 2; | ||||||
| 
 | 
 | ||||||
|     /** |     public UsbSerialDriver getDriver(); | ||||||
|      * Opens and initializes the device as a USB serial device. Upon success, |  | ||||||
|      * caller must ensure that {@link #close()} is eventually called. |  | ||||||
|      * |  | ||||||
|      * @throws IOException on error opening or initializing the device. |  | ||||||
|      */ |  | ||||||
|     public void open() throws IOException; |  | ||||||
|      |      | ||||||
|     /** |     /** | ||||||
|      * Closes the serial device. |      * Port number within driver. | ||||||
|  |      */ | ||||||
|  |     public int getPortNumber(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Opens and initializes the port. Upon success, caller must ensure that | ||||||
|  |      * {@link #close()} is eventually called. | ||||||
|      * |      * | ||||||
|      * @throws IOException on error closing the device. |      * @param connection an open device connection, acquired with | ||||||
|  |      *            {@link UsbManager#openDevice(android.hardware.usb.UsbDevice)} | ||||||
|  |      * @throws IOException on error opening or initializing the port. | ||||||
|  |      */ | ||||||
|  |     public void open(UsbDeviceConnection connection) throws IOException; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Closes the port. | ||||||
|  |      * | ||||||
|  |      * @throws IOException on error closing the port. | ||||||
|      */ |      */ | ||||||
|     public void close() throws IOException; |     public void close() throws IOException; | ||||||
| 
 | 
 | ||||||
| @ -0,0 +1,113 @@ | |||||||
|  | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  |  * | ||||||
|  |  * 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: https://github.com/mik3y/usb-serial-for-android | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package com.hoho.android.usbserial.driver; | ||||||
|  | 
 | ||||||
|  | import android.hardware.usb.UsbDevice; | ||||||
|  | import android.hardware.usb.UsbManager; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Constructor; | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * | ||||||
|  |  * @author mike wakerly (opensource@hoho.com) | ||||||
|  |  */ | ||||||
|  | public class UsbSerialProber { | ||||||
|  | 
 | ||||||
|  |     private final ProbeTable mProbeTable; | ||||||
|  | 
 | ||||||
|  |     public UsbSerialProber(ProbeTable probeTable) { | ||||||
|  |         mProbeTable = probeTable; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UsbSerialProber getDefaultProber() { | ||||||
|  |         return new UsbSerialProber(getDefaultProbeTable()); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public static ProbeTable getDefaultProbeTable() { | ||||||
|  |         final ProbeTable probeTable = new ProbeTable(); | ||||||
|  |         probeTable.addDriver(CdcAcmSerialDriver.class); | ||||||
|  |         probeTable.addDriver(Cp21xxSerialDriver.class); | ||||||
|  |         probeTable.addDriver(FtdiSerialDriver.class); | ||||||
|  |         probeTable.addDriver(ProlificSerialDriver.class); | ||||||
|  |         return probeTable; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Finds and builds all possible {@link UsbSerialDriver UsbSerialDrivers} | ||||||
|  |      * from the currently-attached {@link UsbDevice} hierarchy. This method does | ||||||
|  |      * not require permission from the Android USB system, since it does not | ||||||
|  |      * open any of the devices. | ||||||
|  |      * | ||||||
|  |      * @param usbManager | ||||||
|  |      * @return a list, possibly empty, of all compatible drivers | ||||||
|  |      */ | ||||||
|  |     public List<UsbSerialDriver> findAllDrivers(final UsbManager usbManager) { | ||||||
|  |         final List<UsbSerialDriver> result = new ArrayList<UsbSerialDriver>(); | ||||||
|  | 
 | ||||||
|  |         for (final UsbDevice usbDevice : usbManager.getDeviceList().values()) { | ||||||
|  |             final UsbSerialDriver driver = probeDevice(usbDevice); | ||||||
|  |             if (driver != null) { | ||||||
|  |                 result.add(driver); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     /** | ||||||
|  |      * Probes a single device for a compatible driver. | ||||||
|  |      *  | ||||||
|  |      * @param usbDevice the usb device to probe | ||||||
|  |      * @return a new {@link UsbSerialDriver} compatible with this device, or | ||||||
|  |      *         {@code null} if none available. | ||||||
|  |      */ | ||||||
|  |     public UsbSerialDriver probeDevice(final UsbDevice usbDevice) { | ||||||
|  |         final int vendorId = usbDevice.getVendorId(); | ||||||
|  |         final int productId = usbDevice.getProductId(); | ||||||
|  | 
 | ||||||
|  |         final Class<? extends UsbSerialDriver> driverClass = | ||||||
|  |                 mProbeTable.findDriver(vendorId, productId); | ||||||
|  |         if (driverClass != null) { | ||||||
|  |             final UsbSerialDriver driver; | ||||||
|  |             try { | ||||||
|  |                 final Constructor<? extends UsbSerialDriver> ctor = | ||||||
|  |                         driverClass.getConstructor(UsbDevice.class); | ||||||
|  |                 driver = ctor.newInstance(usbDevice); | ||||||
|  |             } catch (NoSuchMethodException e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } catch (IllegalArgumentException e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } catch (InstantiationException e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } catch (IllegalAccessException e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } catch (InvocationTargetException e) { | ||||||
|  |                 throw new RuntimeException(e); | ||||||
|  |             } | ||||||
|  |             return driver; | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| /* Copyright 2011 Google Inc. | /* Copyright 2011-2013 Google Inc. | ||||||
|  |  * Copyright 2013 mike wakerly <opensource@hoho.com> | ||||||
|  * |  * | ||||||
|  * This library is free software; you can redistribute it and/or |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
| @ -15,7 +16,7 @@ | |||||||
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, | ||||||
|  * USA. |  * USA. | ||||||
|  * |  * | ||||||
|  * Project home page: http://code.google.com/p/usb-serial-for-android/ |  * Project home page: https://github.com/mik3y/usb-serial-for-android | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| package com.hoho.android.usbserial.util; | package com.hoho.android.usbserial.util; | ||||||
| @ -23,13 +24,13 @@ package com.hoho.android.usbserial.util; | |||||||
| import android.hardware.usb.UsbRequest; | import android.hardware.usb.UsbRequest; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
| 
 | 
 | ||||||
| import com.hoho.android.usbserial.driver.UsbSerialDriver; | import com.hoho.android.usbserial.driver.UsbSerialPort; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Utility class which services a {@link UsbSerialDriver} in its {@link #run()} |  * Utility class which services a {@link UsbSerialPort} in its {@link #run()} | ||||||
|  * method. |  * method. | ||||||
|  * |  * | ||||||
|  * @author mike wakerly (opensource@hoho.com) |  * @author mike wakerly (opensource@hoho.com) | ||||||
| @ -42,7 +43,7 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|     private static final int READ_WAIT_MILLIS = 200; |     private static final int READ_WAIT_MILLIS = 200; | ||||||
|     private static final int BUFSIZ = 4096; |     private static final int BUFSIZ = 4096; | ||||||
| 
 | 
 | ||||||
|     private final UsbSerialDriver mDriver; |     private final UsbSerialPort mDriver; | ||||||
| 
 | 
 | ||||||
|     private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ); |     private final ByteBuffer mReadBuffer = ByteBuffer.allocate(BUFSIZ); | ||||||
| 
 | 
 | ||||||
| @ -77,14 +78,14 @@ public class SerialInputOutputManager implements Runnable { | |||||||
|     /** |     /** | ||||||
|      * Creates a new instance with no listener. |      * Creates a new instance with no listener. | ||||||
|      */ |      */ | ||||||
|     public SerialInputOutputManager(UsbSerialDriver driver) { |     public SerialInputOutputManager(UsbSerialPort driver) { | ||||||
|         this(driver, null); |         this(driver, null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Creates a new instance with the provided listener. |      * Creates a new instance with the provided listener. | ||||||
|      */ |      */ | ||||||
|     public SerialInputOutputManager(UsbSerialDriver driver, Listener listener) { |     public SerialInputOutputManager(UsbSerialPort driver, Listener listener) { | ||||||
|         mDriver = driver; |         mDriver = driver; | ||||||
|         mListener = listener; |         mListener = listener; | ||||||
|     } |     } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user