mirror of
https://github.com/mik3y/usb-serial-for-android
synced 2025-06-08 00:16:13 +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