commit
e20b3cc913
|
@ -0,0 +1,4 @@
|
|||
caches
|
||||
codeStyles
|
||||
libraries
|
||||
workspace.xml
|
|
@ -1 +0,0 @@
|
|||
usb-serial-for-android
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
|
@ -1,3 +0,0 @@
|
|||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
|
@ -1,38 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="12">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="android.annotation.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="11">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="android.annotation.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</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_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<settings>
|
||||
<last-edited>1.8</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
305
README.md
305
README.md
|
@ -1,143 +1,162 @@
|
|||
# usb-serial-for-android
|
||||
|
||||
This is a driver library for communication with Arduinos and other USB serial hardware on
|
||||
Android, using the
|
||||
[Android USB Host API](http://developer.android.com/guide/topics/connectivity/usb/host.html)
|
||||
available on Android 3.1+.
|
||||
|
||||
No root access, ADK, or special kernel drivers are required; all drivers are implemented in
|
||||
Java. You get a raw serial port with `read()`, `write()`, and other basic
|
||||
functions for use with your own protocols.
|
||||
|
||||
* **Homepage**: https://github.com/mik3y/usb-serial-for-android
|
||||
* **Google group**: http://groups.google.com/group/usb-serial-for-android
|
||||
* **Latest release**: [v0.1.0](https://github.com/mik3y/usb-serial-for-android/releases)
|
||||
|
||||
## Quick Start
|
||||
|
||||
**1.** [Link your project](https://github.com/mik3y/usb-serial-for-android/wiki/Building-From-Source) to the library.
|
||||
|
||||
**2.** Copy [device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/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).
|
||||
|
||||
```xml
|
||||
<activity
|
||||
android:name="..."
|
||||
...>
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||
android:resource="@xml/device_filter" />
|
||||
</activity>
|
||||
```
|
||||
|
||||
**4.** Use it! Example code snippet:
|
||||
|
||||
```java
|
||||
// Find all available drivers from attached devices.
|
||||
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
|
||||
if (availableDrivers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Open a connection to the first available driver.
|
||||
UsbSerialDriver driver = availableDrivers.get(0);
|
||||
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
|
||||
if (connection == null) {
|
||||
// You probably need to call UsbManager.requestPermission(driver.getDevice(), ..)
|
||||
return;
|
||||
}
|
||||
|
||||
// Read some data! Most have just one port (port 0).
|
||||
UsbSerialPort port = driver.getPorts().get(0);
|
||||
try {
|
||||
port.open(connection);
|
||||
port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
|
||||
|
||||
byte buffer[] = new byte[16];
|
||||
int numBytesRead = port.read(buffer, 1000);
|
||||
Log.d(TAG, "Read " + numBytesRead + " bytes.");
|
||||
} catch (IOException e) {
|
||||
// Deal with error.
|
||||
} finally {
|
||||
port.close();
|
||||
}
|
||||
```
|
||||
|
||||
For a more complete example, see the
|
||||
[UsbSerialExamples project](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples)
|
||||
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)
|
||||
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();
|
||||
customTable.addProduct(0x1234, 0x0001, CdcAcmSerialDriver.class);
|
||||
customTable.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
|
||||
|
||||
* *Serial chips:* FT232R, CDC/ACM (eg Arduino Uno) and possibly others.
|
||||
See [CompatibleSerialDevices](https://github.com/mik3y/usb-serial-for-android/wiki/Compatible-Serial-Devices).
|
||||
* *Android phones and tablets:* Nexus 7, Motorola Xoom, and many others.
|
||||
See [CompatibleAndroidDevices](https://github.com/mik3y/usb-serial-for-android/wiki/Compatible-Android-Devices).
|
||||
|
||||
|
||||
## Author, License, and Copyright
|
||||
|
||||
usb-serial-for-android is written and maintained by *mike wakerly*.
|
||||
|
||||
This library is licensed under *LGPL Version 2.1*. Please see LICENSE.txt for the
|
||||
complete license.
|
||||
|
||||
Copyright 2011-2012, Google Inc. All Rights Reserved.
|
||||
|
||||
Portions of this library are based on libftdi
|
||||
(http://www.intra2net.com/en/developer/libftdi). Please see
|
||||
FtdiSerialDriver.java for more information.
|
||||
|
||||
## Help & Discussion
|
||||
|
||||
For common problems, see the
|
||||
[Troubleshooting](https://github.com/mik3y/usb-serial-for-android/wiki/Troubleshooting)
|
||||
wiki page.
|
||||
|
||||
For other help and discussion, please join our Google Group,
|
||||
[usb-serial-for-android](https://groups.google.com/forum/?fromgroups#!forum/usb-serial-for-android).
|
||||
|
||||
Are you using the library? Let us know on the group and we'll add your project to
|
||||
[ProjectsUsingUsbSerialForAndroid](https://github.com/mik3y/usb-serial-for-android/wiki/Projects-Using-usb-serial-for-android).
|
||||
|
||||
[![Jitpack](https://jitpack.io/v/mik3y/usb-serial-for-android.svg)](https://jitpack.io/#mik3y/usb-serial-for-android)
|
||||
[![Codacy](https://api.codacy.com/project/badge/Grade/4d528e82e35d42d49f659e9b93a9c77d)](https://www.codacy.com/manual/kai-morich/usb-serial-for-android-mik3y?utm_source=github.com&utm_medium=referral&utm_content=mik3y/usb-serial-for-android&utm_campaign=Badge_Grade)
|
||||
[![codecov](https://codecov.io/gh/mik3y/usb-serial-for-android/branch/master/graph/badge.svg)](https://codecov.io/gh/mik3y/usb-serial-for-android)
|
||||
|
||||
# usb-serial-for-android
|
||||
|
||||
This is a driver library for communication with Arduinos and other USB serial hardware on
|
||||
Android, using the
|
||||
[Android USB Host Mode (OTG)](http://developer.android.com/guide/topics/connectivity/usb/host.html)
|
||||
available since Android 3.1 and working reliably since Android 4.2.
|
||||
|
||||
No root access, ADK, or special kernel drivers are required; all drivers are implemented in
|
||||
Java. You get a raw serial port with `read()`, `write()`, and other basic
|
||||
functions for use with your own protocols.
|
||||
|
||||
## Quick Start
|
||||
|
||||
**1.** Add library to your project:
|
||||
|
||||
Add jitpack.io repository to your root build.gradle:
|
||||
```gradle
|
||||
allprojects {
|
||||
repositories {
|
||||
...
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
```
|
||||
Add library to dependencies
|
||||
```gradle
|
||||
dependencies {
|
||||
implementation 'com.github.mik3y:usb-serial-for-android:Tag'
|
||||
}
|
||||
```
|
||||
|
||||
**2.** If the app should be notified when a device is attached, add
|
||||
[device_filter.xml](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples/src/main/res/xml/device_filter.xml)
|
||||
to your project's `res/xml/` directory and configure in your `AndroidManifest.xml`.
|
||||
|
||||
```xml
|
||||
<activity
|
||||
android:name="..."
|
||||
...>
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||
android:resource="@xml/device_filter" />
|
||||
</activity>
|
||||
```
|
||||
|
||||
**3.** Use it! Example code snippet:
|
||||
|
||||
```java
|
||||
// Find all available drivers from attached devices.
|
||||
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
|
||||
if (availableDrivers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Open a connection to the first available driver.
|
||||
UsbSerialDriver driver = availableDrivers.get(0);
|
||||
UsbDeviceConnection connection = manager.openDevice(driver.getDevice());
|
||||
if (connection == null) {
|
||||
// add UsbManager.requestPermission(driver.getDevice(), ..) handling here
|
||||
return;
|
||||
}
|
||||
|
||||
UsbSerialPort port = driver.getPorts().get(0); // Most devices have just one port (port 0)
|
||||
port.open(connection);
|
||||
port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
|
||||
usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
|
||||
Executors.newSingleThreadExecutor().submit(usbIoManager);
|
||||
```
|
||||
```java
|
||||
port.write("hello".getBytes(), WRITE_WAIT_MILLIS);
|
||||
```
|
||||
```java
|
||||
@Override
|
||||
public void onNewData(byte[] data) {
|
||||
runOnUiThread(() -> { textView.append(new String(data)); });
|
||||
}
|
||||
```
|
||||
```java
|
||||
port.close();
|
||||
```
|
||||
|
||||
|
||||
For a simple example, see
|
||||
[UsbSerialExamples](https://github.com/mik3y/usb-serial-for-android/blob/master/usbSerialExamples)
|
||||
folder in this project.
|
||||
|
||||
For a more complete example, see separate github project
|
||||
[SimpleUsbTerminal](https://github.com/kai-morich/SimpleUsbTerminal).
|
||||
|
||||
## 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();
|
||||
customTable.addProduct(0x1234, 0x0001, CdcAcmSerialDriver.class);
|
||||
customTable.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
|
||||
|
||||
This library supports USB to serial converter chips:
|
||||
* FTDI FT232, FT2232, ...
|
||||
* Prolific PL2303
|
||||
* Silabs CP2102, CP2105, ...
|
||||
* Qinheng CH340
|
||||
|
||||
and devices implementing the CDC/ACM protocol like
|
||||
* Arduino using ATmega32U4
|
||||
* Digispark using V-USB software USB
|
||||
* BBC micro:bit using ARM mbed DAPLink firmware
|
||||
* ...
|
||||
|
||||
## Author, License, and Copyright
|
||||
|
||||
usb-serial-for-android is written and maintained by *mike wakerly* and *kai morich*
|
||||
|
||||
This library is licensed under *LGPL Version 2.1*. Please see LICENSE.txt for the
|
||||
complete license.
|
||||
|
||||
Copyright 2011-2012, Google Inc. All Rights Reserved.
|
||||
|
||||
Portions of this library are based on [libftdi](http://www.intra2net.com/en/developer/libftdi).
|
||||
Please see FtdiSerialDriver.java for more information.
|
||||
|
||||
## Help & Discussion
|
||||
|
||||
For common problems, see the
|
||||
[Troubleshooting](https://github.com/mik3y/usb-serial-for-android/wiki/Troubleshooting)
|
||||
wiki page.
|
||||
|
||||
Are you using the library? Add your project to
|
||||
[ProjectsUsingUsbSerialForAndroid](https://github.com/mik3y/usb-serial-for-android/wiki/Projects-Using-usb-serial-for-android).
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/* Copyright 2012 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/
|
||||
*/
|
||||
|
||||
// Sample Arduino sketch for use with usb-serial-for-android.
|
||||
// Prints an ever-increasing counter, and writes back anything
|
||||
// it receives.
|
||||
|
||||
static int counter = 0;
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print("Tick #");
|
||||
Serial.print(counter++, DEC);
|
||||
Serial.print("\n");
|
||||
|
||||
if (Serial.peek() != -1) {
|
||||
Serial.print("Read: ");
|
||||
do {
|
||||
Serial.print((char) Serial.read());
|
||||
} while (Serial.peek() != -1);
|
||||
Serial.print("\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.2.3'
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
#Tue Jun 23 00:11:28 EDT 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
|
||||
#Sun Oct 06 09:46:24 CEST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
|
@ -6,47 +22,6 @@
|
|||
##
|
||||
##############################################################################
|
||||
|
||||
# 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"
|
||||
|
@ -61,9 +36,49 @@ while [ -h "$PRG" ] ; do
|
|||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# 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
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
@ -90,7 +105,7 @@ location of your Java installation."
|
|||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
|
@ -114,6 +129,7 @@ fi
|
|||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
|
@ -154,11 +170,19 @@ if $cygwin ; then
|
|||
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=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem http://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
|
@ -8,14 +24,14 @@
|
|||
@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 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="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
|
@ -46,10 +62,9 @@ echo location of your Java installation.
|
|||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
@rem Get command-line arguments, handling Windows 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.
|
||||
|
@ -60,11 +75,6 @@ set _SKIP=2
|
|||
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
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
bridge USB-serial to hardware-serial
|
||||
|
||||
for Arduinos based on ATmega32u4 (Leonardo and compatible Pro Micro, Micro)
|
||||
hardware serial is configured with baud-rate, databits, stopbits, parity as send over USB
|
||||
|
||||
see https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/cores/arduino
|
||||
-> CDC.cpp|HardwareSerial.cpp for serial implementation details
|
||||
|
||||
this sketch is mainly for demonstration / test of CDC communication
|
||||
performance as real usb-serial bridge would be inacceptable as each byte is send in separate USB packet
|
||||
*/
|
||||
|
||||
uint32_t baud = 9600;
|
||||
uint8_t databits = 8;
|
||||
uint8_t stopbits = 1;
|
||||
uint8_t parity = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(baud); // USB
|
||||
Serial1.begin(baud, SERIAL_8N1);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// show USB connected state
|
||||
if (Serial) TXLED1;
|
||||
else TXLED0;
|
||||
|
||||
// configure hardware serial
|
||||
if (Serial.baud() != baud ||
|
||||
Serial.numbits() != databits ||
|
||||
Serial.stopbits() != stopbits ||
|
||||
Serial.paritytype() != parity) {
|
||||
baud = Serial.baud();
|
||||
databits = Serial.numbits();
|
||||
stopbits = Serial.stopbits();
|
||||
parity = Serial.paritytype();
|
||||
uint8_t config = 0; // ucsrc register
|
||||
switch (databits) {
|
||||
case 5: break;
|
||||
case 6: config |= 2; break;
|
||||
case 7: config |= 4; break;
|
||||
case 8: config |= 6; break;
|
||||
default: config |= 6;
|
||||
}
|
||||
switch (stopbits) {
|
||||
case 2: config |= 8;
|
||||
// 1.5 stopbits not supported
|
||||
}
|
||||
switch (parity) {
|
||||
case 1: config |= 0x30; break; // odd
|
||||
case 2: config |= 0x20; break; // even
|
||||
// mark, space not supported
|
||||
}
|
||||
Serial1.end();
|
||||
Serial1.begin(baud, config);
|
||||
}
|
||||
|
||||
// bridge
|
||||
if (Serial.available() > 0)
|
||||
Serial1.write(Serial.read());
|
||||
if (Serial1.available() > 0)
|
||||
Serial.write(Serial1.read());
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
*** /n/archiv/python/rfc2217_server.py 2018-03-10 09:02:07.613771600 +0100
|
||||
--- rfc2217_server.py 2018-03-09 20:57:44.933717100 +0100
|
||||
***************
|
||||
*** 26,31 ****
|
||||
--- 26,32 ----
|
||||
self,
|
||||
logger=logging.getLogger('rfc2217.server') if debug else None)
|
||||
self.log = logging.getLogger('redirector')
|
||||
+ self.dlog = logging.getLogger('data')
|
||||
|
||||
def statusline_poller(self):
|
||||
self.log.debug('status line poll thread started')
|
||||
***************
|
||||
*** 55,60 ****
|
||||
--- 56,62 ----
|
||||
try:
|
||||
data = self.serial.read(self.serial.in_waiting or 1)
|
||||
if data:
|
||||
+ self.dlog.debug("serial read: "+data.encode('hex'))
|
||||
# escape outgoing data when needed (Telnet IAC (0xff) character)
|
||||
self.write(b''.join(self.rfc2217.escape(data)))
|
||||
except socket.error as msg:
|
||||
***************
|
||||
*** 76,81 ****
|
||||
--- 78,84 ----
|
||||
data = self.socket.recv(1024)
|
||||
if not data:
|
||||
break
|
||||
+ self.dlog.debug("socket read: "+data.encode('hex'))
|
||||
self.serial.write(b''.join(self.rfc2217.filter(data)))
|
||||
except socket.error as msg:
|
||||
self.log.error('{}'.format(msg))
|
||||
***************
|
||||
*** 132,137 ****
|
||||
--- 135,141 ----
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
#~ logging.getLogger('root').setLevel(logging.INFO)
|
||||
logging.getLogger('rfc2217').setLevel(level)
|
||||
+ logging.getLogger('data').setLevel(level)
|
||||
|
||||
# connect to serial port
|
||||
ser = serial.serial_for_url(args.SERIALPORT, do_not_open=True)
|
|
@ -1,15 +1,15 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "22.0.1"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '28.0.3'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 22
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 28
|
||||
|
||||
testApplicationId "com.hoho.android.usbserial.examples"
|
||||
testInstrumentationRunner "android.test.InstrumentationTestRunner"
|
||||
missingDimensionStrategy 'device', 'anyDevice'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -20,5 +20,5 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':usbSerialForAndroid')
|
||||
implementation project(':usbSerialForAndroid')
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="12" />
|
||||
|
||||
<uses-feature android:name="android.hardware.usb.host" />
|
||||
|
||||
<application
|
||||
|
|
|
@ -22,7 +22,11 @@
|
|||
package com.hoho.android.usbserial.examples;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -39,12 +43,12 @@ import android.widget.ArrayAdapter;
|
|||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.TwoLineListItem;
|
||||
|
||||
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.util.HexDump;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -59,12 +63,14 @@ public class DeviceListActivity extends Activity {
|
|||
private final String TAG = DeviceListActivity.class.getSimpleName();
|
||||
|
||||
private UsbManager mUsbManager;
|
||||
private UsbSerialPort mSerialPort;
|
||||
private ListView mListView;
|
||||
private TextView mProgressBarTitle;
|
||||
private ProgressBar mProgressBar;
|
||||
|
||||
private static final int MESSAGE_REFRESH = 101;
|
||||
private static final long REFRESH_TIMEOUT_MILLIS = 5000;
|
||||
public static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
@Override
|
||||
|
@ -81,6 +87,7 @@ public class DeviceListActivity extends Activity {
|
|||
}
|
||||
|
||||
};
|
||||
private BroadcastReceiver mUsbReceiver;
|
||||
|
||||
private List<UsbSerialPort> mEntries = new ArrayList<UsbSerialPort>();
|
||||
private ArrayAdapter<UsbSerialPort> mAdapter;
|
||||
|
@ -89,11 +96,25 @@ public class DeviceListActivity extends Activity {
|
|||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
final Context context = this;
|
||||
|
||||
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
mListView = (ListView) findViewById(R.id.deviceList);
|
||||
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||
mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
|
||||
mListView = findViewById(R.id.deviceList);
|
||||
mProgressBar = findViewById(R.id.progressBar);
|
||||
mProgressBarTitle = findViewById(R.id.progressBarTitle);
|
||||
|
||||
mUsbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if(intent.getAction().equals(INTENT_ACTION_GRANT_USB)) {
|
||||
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
|
||||
showConsoleActivity(mSerialPort);
|
||||
} else {
|
||||
Toast.makeText(context, "USB permission denied", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mAdapter = new ArrayAdapter<UsbSerialPort>(this,
|
||||
android.R.layout.simple_expandable_list_item_2, mEntries) {
|
||||
|
@ -112,9 +133,7 @@ public class DeviceListActivity extends Activity {
|
|||
final UsbSerialDriver driver = port.getDriver();
|
||||
final UsbDevice device = driver.getDevice();
|
||||
|
||||
final String title = String.format("Vendor %s Product %s",
|
||||
HexDump.toHexString((short) device.getVendorId()),
|
||||
HexDump.toHexString((short) device.getProductId()));
|
||||
final String title = String.format("Vendor %4X Product %4X", device.getVendorId(), device.getProductId());
|
||||
row.getText1().setText(title);
|
||||
|
||||
final String subtitle = driver.getClass().getSimpleName();
|
||||
|
@ -135,8 +154,14 @@ public class DeviceListActivity extends Activity {
|
|||
return;
|
||||
}
|
||||
|
||||
final UsbSerialPort port = mEntries.get(position);
|
||||
showConsoleActivity(port);
|
||||
mSerialPort = mEntries.get(position);
|
||||
UsbDevice device = mSerialPort.getDriver().getDevice();
|
||||
if (!mUsbManager.hasPermission(device)) {
|
||||
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
|
||||
mUsbManager.requestPermission(device, usbPermissionIntent);
|
||||
} else {
|
||||
showConsoleActivity(mSerialPort);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -145,12 +170,14 @@ public class DeviceListActivity extends Activity {
|
|||
protected void onResume() {
|
||||
super.onResume();
|
||||
mHandler.sendEmptyMessage(MESSAGE_REFRESH);
|
||||
registerReceiver(mUsbReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mHandler.removeMessages(MESSAGE_REFRESH);
|
||||
unregisterReceiver(mUsbReceiver);
|
||||
}
|
||||
|
||||
private void refreshDeviceList() {
|
|
@ -1,14 +1,17 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "19.1"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '28.0.3'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 12
|
||||
targetSdkVersion 19
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 28
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunnerArguments = [ // Raspi Windows LinuxVM ...
|
||||
'rfc2217_server_host': '192.168.0.100',
|
||||
'rfc2217_server_nonstandard_baudrates': 'true', // true false false
|
||||
]
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -19,81 +22,14 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
group = "com.hoho.android"
|
||||
version = "0.2.0-SNAPSHOT"
|
||||
|
||||
configurations {
|
||||
archives {
|
||||
extendsFrom configurations.default
|
||||
}
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support:support-annotations:28.0.0'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'commons-net:commons-net:3.6'
|
||||
androidTestImplementation 'org.apache.commons:commons-lang3:3.8.1'
|
||||
}
|
||||
|
||||
signing {
|
||||
required { has("release") && gradle.taskGraph.hasTask("uploadArchives") }
|
||||
sign configurations.archives
|
||||
}
|
||||
//apply from: 'publishToMavenLocal.gradle'
|
||||
|
||||
def getRepositoryUsername() {
|
||||
return hasProperty('sonatypeUsername') ? sonatypeUsername : ""
|
||||
}
|
||||
|
||||
def getRepositoryPassword() {
|
||||
return hasProperty('sonatypePassword') ? sonatypePassword : ""
|
||||
}
|
||||
|
||||
def isReleaseBuild() {
|
||||
return version.contains("SNAPSHOT") == false
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
def sonatypeRepositoryUrl
|
||||
if (isReleaseBuild()) {
|
||||
println 'RELEASE BUILD'
|
||||
sonatypeRepositoryUrl = hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
|
||||
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
} else {
|
||||
println 'SNAPSHOT BUILD'
|
||||
sonatypeRepositoryUrl = hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
|
||||
: "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
|
||||
configuration = configurations.archives
|
||||
repositories.mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
repository(url: sonatypeRepositoryUrl) {
|
||||
authentication(userName: getRepositoryUsername(),
|
||||
password: getRepositoryPassword())
|
||||
}
|
||||
|
||||
pom.artifactId = 'usb-serial-for-android'
|
||||
pom.project {
|
||||
name 'usb-serial-for-android'
|
||||
packaging 'aar'
|
||||
description 'USB Serial Driver Library for Android'
|
||||
url 'https://github.com/mik3y/usb-serial-for-android'
|
||||
|
||||
scm {
|
||||
url 'scm:git@github.com:mik3y/usb-serial-for-android.git'
|
||||
connection 'scm:git@github.com:mik3y/usb-serial-for-android.git'
|
||||
developerConnection 'scm:git@github.com:mik3y/usb-serial-for-android.git'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'GNU LGPL v2.1'
|
||||
url 'http://www.gnu.org/licenses/lgpl-2.1.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id 'mik3y'
|
||||
name 'mik3y'
|
||||
email 'opensource@hoho.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//apply from: 'coverage.gradle'
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
apply plugin: 'jacoco'
|
||||
|
||||
android {
|
||||
flavorDimensions 'device'
|
||||
productFlavors {
|
||||
anyDevice {
|
||||
// Used as fallback in usbSerialExample/build.gradle -> missingDimensionStrategy, but not for coverage report
|
||||
dimension 'device'
|
||||
}
|
||||
arduino {
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'CdcAcm']
|
||||
}
|
||||
ch340 {
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Ch34x']
|
||||
}
|
||||
cp2102 { // and cp2105 first port
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Cp21xx']
|
||||
}
|
||||
cp2105 { // second port
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Cp21xx', 'test_device_port': '1']
|
||||
}
|
||||
ft232 { // and ft2232 first port
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Ftdi']
|
||||
}
|
||||
ft2232 { // second port
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Ftdi', 'test_device_port': '1']
|
||||
}
|
||||
pl2302 {
|
||||
dimension 'device'
|
||||
testInstrumentationRunnerArguments = ['test_device_driver': 'Prolific']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
testCoverageEnabled true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
apply plugin: 'maven-publish'
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
groupId 'com.github.mik3y'
|
||||
artifactId 'usb-serial-for-android'
|
||||
version '1.x.0'
|
||||
afterEvaluate {
|
||||
artifact androidSourcesJar
|
||||
artifact bundleReleaseAar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
classifier 'sources'
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.hoho.android.usbserial"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.hoho.android.usbserial"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk android:minSdkVersion="12" />
|
||||
package="com.hoho.android.usbserial">
|
||||
</manifest>
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package com.hoho.android.usbserial;
|
||||
|
||||
/**
|
||||
* Static container of information about this library.
|
||||
*/
|
||||
public final class BuildInfo {
|
||||
|
||||
/**
|
||||
* The current version of this library. Values are of the form
|
||||
* "major.minor.micro[-suffix]". A suffix of "-pre" indicates a pre-release
|
||||
* of the version preceeding it.
|
||||
*/
|
||||
public static final String VERSION = "0.2.0-pre";
|
||||
|
||||
private BuildInfo() {
|
||||
throw new IllegalStateException("Non-instantiable class.");
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,6 @@ 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;
|
||||
|
@ -51,6 +50,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
|
||||
private final UsbDevice mDevice;
|
||||
private final UsbSerialPort mPort;
|
||||
private UsbRequest mUsbRequest;
|
||||
|
||||
public CdcAcmSerialDriver(UsbDevice device) {
|
||||
mDevice = device;
|
||||
|
@ -69,7 +69,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
|
||||
class CdcAcmSerialPort extends CommonUsbSerialPort {
|
||||
|
||||
private final boolean mEnableAsyncReads;
|
||||
private UsbInterface mControlInterface;
|
||||
private UsbInterface mDataInterface;
|
||||
|
||||
|
@ -77,6 +76,8 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
private UsbEndpoint mReadEndpoint;
|
||||
private UsbEndpoint mWriteEndpoint;
|
||||
|
||||
private int mControlIndex;
|
||||
|
||||
private boolean mRts = false;
|
||||
private boolean mDtr = false;
|
||||
|
||||
|
@ -90,7 +91,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
|
||||
public CdcAcmSerialPort(UsbDevice device, int portNumber) {
|
||||
super(device, portNumber);
|
||||
mEnableAsyncReads = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,13 +116,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
openInterface();
|
||||
}
|
||||
|
||||
if (mEnableAsyncReads) {
|
||||
Log.d(TAG, "Async reads enabled");
|
||||
} else {
|
||||
Log.d(TAG, "Async reads disabled.");
|
||||
}
|
||||
|
||||
|
||||
opened = true;
|
||||
} finally {
|
||||
if (!opened) {
|
||||
|
@ -139,6 +132,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
// the following code is inspired by the cdc-acm driver
|
||||
// in the linux kernel
|
||||
|
||||
mControlIndex = 0;
|
||||
mControlInterface = mDevice.getInterface(0);
|
||||
Log.d(TAG, "Control iface=" + mControlInterface);
|
||||
|
||||
|
@ -196,34 +190,63 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
private void openInterface() throws IOException {
|
||||
Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount());
|
||||
|
||||
mControlInterface = mDevice.getInterface(0);
|
||||
mControlInterface = null;
|
||||
mDataInterface = null;
|
||||
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
|
||||
UsbInterface usbInterface = mDevice.getInterface(i);
|
||||
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM) {
|
||||
mControlIndex = i;
|
||||
mControlInterface = usbInterface;
|
||||
}
|
||||
if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) {
|
||||
mDataInterface = usbInterface;
|
||||
}
|
||||
}
|
||||
|
||||
if(mControlInterface == null) {
|
||||
throw new IOException("no control interface.");
|
||||
}
|
||||
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());
|
||||
if (mControlEndpoint.getDirection() != UsbConstants.USB_DIR_IN || mControlEndpoint.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) {
|
||||
throw new IOException("invalid control endpoint");
|
||||
}
|
||||
|
||||
Log.d(TAG, "Claiming data interface.");
|
||||
mDataInterface = mDevice.getInterface(1);
|
||||
if(mDataInterface == null) {
|
||||
throw new IOException("no data interface.");
|
||||
}
|
||||
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());
|
||||
|
||||
mReadEndpoint = null;
|
||||
mWriteEndpoint = null;
|
||||
for (int i = 0; i < mDataInterface.getEndpointCount(); i++) {
|
||||
UsbEndpoint ep = mDataInterface.getEndpoint(i);
|
||||
if (ep.getDirection() == UsbConstants.USB_DIR_IN && ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
|
||||
mReadEndpoint = ep;
|
||||
if (ep.getDirection() == UsbConstants.USB_DIR_OUT && ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)
|
||||
mWriteEndpoint = ep;
|
||||
}
|
||||
if (mReadEndpoint == null || mWriteEndpoint == null) {
|
||||
throw new IOException("Could not get read&write endpoints.");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
private int sendAcmControlMessage(int request, int value, byte[] buf) throws IOException {
|
||||
int len = mConnection.controlTransfer(
|
||||
USB_RT_ACM, request, value, mControlIndex, buf, buf != null ? buf.length : 0, 5000);
|
||||
if(len < 0) {
|
||||
throw new IOException("controlTransfer failed.");
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -231,57 +254,43 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
if (mConnection == null) {
|
||||
throw new IOException("Already closed");
|
||||
}
|
||||
synchronized (this) {
|
||||
if (mUsbRequest != null)
|
||||
mUsbRequest.cancel();
|
||||
}
|
||||
mConnection.close();
|
||||
mConnection = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] dest, int timeoutMillis) throws IOException {
|
||||
if (mEnableAsyncReads) {
|
||||
final UsbRequest request = new UsbRequest();
|
||||
try {
|
||||
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.");
|
||||
throw new IOException("Error queueing request.");
|
||||
}
|
||||
|
||||
mUsbRequest = request;
|
||||
final UsbRequest response = mConnection.requestWait();
|
||||
synchronized (this) {
|
||||
mUsbRequest = null;
|
||||
}
|
||||
if (response == null) {
|
||||
throw new IOException("Null response");
|
||||
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;
|
||||
//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);
|
||||
} finally {
|
||||
mUsbRequest = null;
|
||||
request.close();
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -320,7 +329,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setParameters(int baudRate, int dataBits, int stopBits, int parity) {
|
||||
public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException {
|
||||
byte stopBitsByte;
|
||||
switch (stopBits) {
|
||||
case STOPBITS_1: stopBitsByte = 0; break;
|
||||
|
@ -392,7 +401,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
setDtrRts();
|
||||
}
|
||||
|
||||
private void setDtrRts() {
|
||||
private void setDtrRts() throws IOException {
|
||||
int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
|
||||
sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
|
||||
}
|
||||
|
@ -401,7 +410,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
|
||||
public static Map<Integer, int[]> getSupportedDevices() {
|
||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO),
|
||||
supportedDevices.put(UsbId.VENDOR_ARDUINO,
|
||||
new int[] {
|
||||
UsbId.ARDUINO_UNO,
|
||||
UsbId.ARDUINO_UNO_R3,
|
||||
|
@ -414,18 +423,22 @@ public class CdcAcmSerialDriver implements UsbSerialDriver {
|
|||
UsbId.ARDUINO_LEONARDO,
|
||||
UsbId.ARDUINO_MICRO,
|
||||
});
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH),
|
||||
supportedDevices.put(UsbId.VENDOR_VAN_OOIJEN_TECH,
|
||||
new int[] {
|
||||
UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL,
|
||||
});
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ATMEL),
|
||||
supportedDevices.put(UsbId.VENDOR_ATMEL,
|
||||
new int[] {
|
||||
UsbId.ATMEL_LUFA_CDC_DEMO_APP,
|
||||
});
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_LEAFLABS),
|
||||
supportedDevices.put(UsbId.VENDOR_LEAFLABS,
|
||||
new int[] {
|
||||
UsbId.LEAFLABS_MAPLE,
|
||||
});
|
||||
supportedDevices.put(UsbId.VENDOR_ARM,
|
||||
new int[] {
|
||||
UsbId.ARM_MBED,
|
||||
});
|
||||
return supportedDevices;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,11 @@ 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.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -46,6 +48,17 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
private final UsbDevice mDevice;
|
||||
private final UsbSerialPort mPort;
|
||||
|
||||
private static final int LCR_ENABLE_RX = 0x80;
|
||||
private static final int LCR_ENABLE_TX = 0x40;
|
||||
private static final int LCR_MARK_SPACE = 0x20;
|
||||
private static final int LCR_PAR_EVEN = 0x10;
|
||||
private static final int LCR_ENABLE_PAR = 0x08;
|
||||
private static final int LCR_STOP_BITS_2 = 0x04;
|
||||
private static final int LCR_CS8 = 0x03;
|
||||
private static final int LCR_CS7 = 0x02;
|
||||
private static final int LCR_CS6 = 0x01;
|
||||
private static final int LCR_CS5 = 0x00;
|
||||
|
||||
public Ch34xSerialDriver(UsbDevice device) {
|
||||
mDevice = device;
|
||||
mPort = new Ch340SerialPort(mDevice, 0);
|
||||
|
@ -72,6 +85,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
|
||||
private UsbEndpoint mReadEndpoint;
|
||||
private UsbEndpoint mWriteEndpoint;
|
||||
private UsbRequest mUsbRequest;
|
||||
|
||||
public Ch340SerialPort(UsbDevice device, int portNumber) {
|
||||
super(device, portNumber);
|
||||
|
@ -93,10 +107,8 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
try {
|
||||
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
|
||||
UsbInterface usbIface = mDevice.getInterface(i);
|
||||
if (mConnection.claimInterface(usbIface, true)) {
|
||||
Log.d(TAG, "claimInterface " + i + " SUCCESS");
|
||||
} else {
|
||||
Log.d(TAG, "claimInterface " + i + " FAIL");
|
||||
if (!mConnection.claimInterface(usbIface, true)) {
|
||||
throw new IOException("Could not claim data interface.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +124,6 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
initialize();
|
||||
setBaudRate(DEFAULT_BAUD_RATE);
|
||||
|
||||
|
@ -133,9 +144,10 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
if (mConnection == null) {
|
||||
throw new IOException("Already closed");
|
||||
}
|
||||
|
||||
// TODO: nothing sended on close, maybe needed?
|
||||
|
||||
synchronized (this) {
|
||||
if (mUsbRequest != null)
|
||||
mUsbRequest.cancel();
|
||||
}
|
||||
try {
|
||||
mConnection.close();
|
||||
} finally {
|
||||
|
@ -146,21 +158,33 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@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
|
||||
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.");
|
||||
}
|
||||
mUsbRequest = request;
|
||||
final UsbRequest response = mConnection.requestWait();
|
||||
synchronized (this) {
|
||||
mUsbRequest = null;
|
||||
}
|
||||
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;
|
||||
}
|
||||
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
|
||||
} finally {
|
||||
mUsbRequest = null;
|
||||
request.close();
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -252,7 +276,7 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
|
||||
checkState("init #4", 0x95, 0x2518, new int[]{-1 /* 0x56, c3*/, 0x00});
|
||||
|
||||
if (controlOut(0x9a, 0x2518, 0x0050) < 0) {
|
||||
if (controlOut(0x9a, 0x2518, LCR_ENABLE_RX | LCR_ENABLE_TX | LCR_CS8) < 0) {
|
||||
throw new IOException("init failed! #5");
|
||||
}
|
||||
|
||||
|
@ -271,36 +295,93 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
|
||||
|
||||
private void setBaudRate(int baudRate) throws IOException {
|
||||
int[] baud = new int[]{2400, 0xd901, 0x0038, 4800, 0x6402,
|
||||
0x001f, 9600, 0xb202, 0x0013, 19200, 0xd902, 0x000d, 38400,
|
||||
0x6403, 0x000a, 115200, 0xcc03, 0x0008};
|
||||
final long CH341_BAUDBASE_FACTOR = 1532620800;
|
||||
final int CH341_BAUDBASE_DIVMAX = 3;
|
||||
|
||||
for (int i = 0; i < baud.length / 3; i++) {
|
||||
if (baud[i * 3] == baudRate) {
|
||||
int ret = controlOut(0x9a, 0x1312, baud[i * 3 + 1]);
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting baud rate. #1");
|
||||
}
|
||||
ret = controlOut(0x9a, 0x0f2c, baud[i * 3 + 2]);
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting baud rate. #1");
|
||||
long factor = CH341_BAUDBASE_FACTOR / baudRate;
|
||||
int divisor = CH341_BAUDBASE_DIVMAX;
|
||||
|
||||
while ((factor > 0xfff0) && divisor > 0) {
|
||||
factor >>= 3;
|
||||
divisor--;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (factor > 0xfff0) {
|
||||
throw new IOException("Baudrate " + baudRate + " not supported");
|
||||
}
|
||||
|
||||
factor = 0x10000 - factor;
|
||||
|
||||
throw new IOException("Baud rate " + baudRate + " currently not supported");
|
||||
int ret = controlOut(0x9a, 0x1312, (int) ((factor & 0xff00) | divisor));
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting baud rate. #1)");
|
||||
}
|
||||
|
||||
ret = controlOut(0x9a, 0x0f2c, (int) (factor & 0xff));
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting baud rate. #2");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setParameters(int baudRate, int dataBits, int stopBits, int parity)
|
||||
throws IOException {
|
||||
setBaudRate(baudRate);
|
||||
|
||||
// TODO databit, stopbit and paraty set not implemented
|
||||
int lcr = LCR_ENABLE_RX | LCR_ENABLE_TX;
|
||||
|
||||
switch (dataBits) {
|
||||
case DATABITS_5:
|
||||
lcr |= LCR_CS5;
|
||||
break;
|
||||
case DATABITS_6:
|
||||
lcr |= LCR_CS6;
|
||||
break;
|
||||
case DATABITS_7:
|
||||
lcr |= LCR_CS7;
|
||||
break;
|
||||
case DATABITS_8:
|
||||
lcr |= LCR_CS8;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown dataBits value: " + dataBits);
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case PARITY_NONE:
|
||||
break;
|
||||
case PARITY_ODD:
|
||||
lcr |= LCR_ENABLE_PAR;
|
||||
break;
|
||||
case PARITY_EVEN:
|
||||
lcr |= LCR_ENABLE_PAR | LCR_PAR_EVEN;
|
||||
break;
|
||||
case PARITY_MARK:
|
||||
lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE;
|
||||
break;
|
||||
case PARITY_SPACE:
|
||||
lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE | LCR_PAR_EVEN;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown parity value: " + parity);
|
||||
}
|
||||
|
||||
switch (stopBits) {
|
||||
case STOPBITS_1:
|
||||
break;
|
||||
case STOPBITS_1_5:
|
||||
throw new IllegalArgumentException("Unsupported stopBits value: 1.5");
|
||||
case STOPBITS_2:
|
||||
lcr |= LCR_STOP_BITS_2;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
|
||||
}
|
||||
|
||||
int ret = controlOut(0x9a, 0x2518, lcr);
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting control byte");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -345,11 +426,6 @@ public class Ch34xSerialDriver implements UsbSerialDriver {
|
|||
writeHandshakeByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Map<Integer, int[]> getSupportedDevices() {
|
||||
|
|
|
@ -160,8 +160,8 @@ abstract class CommonUsbSerialPort implements UsbSerialPort {
|
|||
public abstract void setRTS(boolean value) throws IOException;
|
||||
|
||||
@Override
|
||||
public boolean purgeHwBuffers(boolean flushReadBuffers, boolean flushWriteBuffers) throws IOException {
|
||||
return !flushReadBuffers && !flushWriteBuffers;
|
||||
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,10 +26,12 @@ 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.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -39,11 +41,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
private static final String TAG = Cp21xxSerialDriver.class.getSimpleName();
|
||||
|
||||
private final UsbDevice mDevice;
|
||||
private final UsbSerialPort mPort;
|
||||
private final List<UsbSerialPort> mPorts;
|
||||
|
||||
public Cp21xxSerialDriver(UsbDevice device) {
|
||||
mDevice = device;
|
||||
mPort = new Cp21xxSerialPort(mDevice, 0);
|
||||
mPorts = new ArrayList<>();
|
||||
for( int port = 0; port < device.getInterfaceCount(); port++) {
|
||||
mPorts.add(new Cp21xxSerialPort(mDevice, port));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,7 +58,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@Override
|
||||
public List<UsbSerialPort> getPorts() {
|
||||
return Collections.singletonList(mPort);
|
||||
return mPorts;
|
||||
}
|
||||
|
||||
public class Cp21xxSerialPort extends CommonUsbSerialPort {
|
||||
|
@ -103,6 +108,11 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
private UsbEndpoint mReadEndpoint;
|
||||
private UsbEndpoint mWriteEndpoint;
|
||||
private UsbRequest mUsbRequest;
|
||||
|
||||
// second port of Cp2105 has limited baudRate, dataBits, stopBits, parity
|
||||
// unsupported baudrate returns error at controlTransfer(), other parameters are silently ignored
|
||||
private boolean mIsRestrictedPort;
|
||||
|
||||
public Cp21xxSerialPort(UsbDevice device, int portNumber) {
|
||||
super(device, portNumber);
|
||||
|
@ -115,7 +125,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
private int setConfigSingle(int request, int value) {
|
||||
return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, value,
|
||||
0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
mPortNumber, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,17 +136,15 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
mConnection = connection;
|
||||
boolean opened = false;
|
||||
mIsRestrictedPort = mDevice.getInterfaceCount() == 2 && mPortNumber == 1;
|
||||
try {
|
||||
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
|
||||
UsbInterface usbIface = mDevice.getInterface(i);
|
||||
if (mConnection.claimInterface(usbIface, true)) {
|
||||
Log.d(TAG, "claimInterface " + i + " SUCCESS");
|
||||
} else {
|
||||
Log.d(TAG, "claimInterface " + i + " FAIL");
|
||||
}
|
||||
if(mPortNumber >= mDevice.getInterfaceCount()) {
|
||||
throw new IOException("Unknown port number");
|
||||
}
|
||||
UsbInterface dataIface = mDevice.getInterface(mPortNumber);
|
||||
if (!mConnection.claimInterface(dataIface, true)) {
|
||||
throw new IOException("Could not claim interface " + mPortNumber);
|
||||
}
|
||||
|
||||
UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1);
|
||||
for (int i = 0; i < dataIface.getEndpointCount(); i++) {
|
||||
UsbEndpoint ep = dataIface.getEndpoint(i);
|
||||
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
|
||||
|
@ -169,8 +177,16 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
if (mConnection == null) {
|
||||
throw new IOException("Already closed");
|
||||
}
|
||||
synchronized (this) {
|
||||
if(mUsbRequest != null) {
|
||||
mUsbRequest.cancel();
|
||||
}
|
||||
}
|
||||
try {
|
||||
setConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
|
||||
} catch (Exception ignored)
|
||||
{}
|
||||
try {
|
||||
mConnection.close();
|
||||
} finally {
|
||||
mConnection = null;
|
||||
|
@ -179,21 +195,33 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@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
|
||||
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.");
|
||||
}
|
||||
mUsbRequest = request;
|
||||
final UsbRequest response = mConnection.requestWait();
|
||||
synchronized (this) {
|
||||
mUsbRequest = null;
|
||||
}
|
||||
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;
|
||||
}
|
||||
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
|
||||
} finally {
|
||||
mUsbRequest = null;
|
||||
request.close();
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,7 +266,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
(byte) ((baudRate >> 24) & 0xff)
|
||||
};
|
||||
int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
|
||||
0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
|
||||
0, mPortNumber, data, 4, USB_WRITE_TIMEOUT_MILLIS);
|
||||
if (ret < 0) {
|
||||
throw new IOException("Error setting baud rate.");
|
||||
}
|
||||
|
@ -252,38 +280,62 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
int configDataBits = 0;
|
||||
switch (dataBits) {
|
||||
case DATABITS_5:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
|
||||
configDataBits |= 0x0500;
|
||||
break;
|
||||
case DATABITS_6:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
|
||||
configDataBits |= 0x0600;
|
||||
break;
|
||||
case DATABITS_7:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
|
||||
configDataBits |= 0x0700;
|
||||
break;
|
||||
case DATABITS_8:
|
||||
configDataBits |= 0x0800;
|
||||
break;
|
||||
default:
|
||||
configDataBits |= 0x0800;
|
||||
break;
|
||||
throw new IllegalArgumentException("Unknown dataBits value: " + dataBits);
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case PARITY_NONE:
|
||||
break;
|
||||
case PARITY_ODD:
|
||||
configDataBits |= 0x0010;
|
||||
break;
|
||||
case PARITY_EVEN:
|
||||
configDataBits |= 0x0020;
|
||||
break;
|
||||
case PARITY_MARK:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported parity value: mark");
|
||||
configDataBits |= 0x0030;
|
||||
break;
|
||||
case PARITY_SPACE:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported parity value: space");
|
||||
configDataBits |= 0x0040;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown parity value: " + parity);
|
||||
}
|
||||
|
||||
switch (stopBits) {
|
||||
case STOPBITS_1:
|
||||
configDataBits |= 0;
|
||||
break;
|
||||
case STOPBITS_1_5:
|
||||
throw new IllegalArgumentException("Unsupported stopBits value: 1.5");
|
||||
case STOPBITS_2:
|
||||
if(mIsRestrictedPort)
|
||||
throw new IllegalArgumentException("Unsupported stopBits value: 2");
|
||||
configDataBits |= 2;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
|
||||
}
|
||||
setConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
|
||||
}
|
||||
|
@ -327,8 +379,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean purgeHwBuffers(boolean purgeReadBuffers,
|
||||
boolean purgeWriteBuffers) throws IOException {
|
||||
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
||||
int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
|
||||
| (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
|
||||
|
||||
|
@ -343,7 +394,7 @@ public class Cp21xxSerialDriver implements UsbSerialDriver {
|
|||
|
||||
public static Map<Integer, int[]> getSupportedDevices() {
|
||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_SILABS),
|
||||
supportedDevices.put(UsbId.VENDOR_SILABS,
|
||||
new int[] {
|
||||
UsbId.SILABS_CP2102,
|
||||
UsbId.SILABS_CP2105,
|
||||
|
|
|
@ -28,11 +28,9 @@ 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.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -72,6 +70,8 @@ import java.util.Map;
|
|||
* Supported and tested devices:
|
||||
* <ul>
|
||||
* <li>{@value DeviceType#TYPE_R}</li>
|
||||
* <li>{@value DeviceType#TYPE_2232H}</li>
|
||||
* <li>{@value DeviceType#TYPE_4232H}</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
|
@ -79,8 +79,6 @@ import java.util.Map;
|
|||
* feedback or patches):
|
||||
* <ul>
|
||||
* <li>{@value DeviceType#TYPE_2232C}</li>
|
||||
* <li>{@value DeviceType#TYPE_2232H}</li>
|
||||
* <li>{@value DeviceType#TYPE_4232H}</li>
|
||||
* <li>{@value DeviceType#TYPE_AM}</li>
|
||||
* <li>{@value DeviceType#TYPE_BM}</li>
|
||||
* </ul>
|
||||
|
@ -95,7 +93,7 @@ import java.util.Map;
|
|||
public class FtdiSerialDriver implements UsbSerialDriver {
|
||||
|
||||
private final UsbDevice mDevice;
|
||||
private final UsbSerialPort mPort;
|
||||
private final List<UsbSerialPort> mPorts;
|
||||
|
||||
/**
|
||||
* FTDI chip types.
|
||||
|
@ -106,8 +104,12 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
public FtdiSerialDriver(UsbDevice device) {
|
||||
mDevice = device;
|
||||
mPort = new FtdiSerialPort(mDevice, 0);
|
||||
mPorts = new ArrayList<>();
|
||||
for( int port = 0; port < device.getInterfaceCount(); port++) {
|
||||
mPorts.add(new FtdiSerialPort(mDevice, port));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsbDevice getDevice() {
|
||||
return mDevice;
|
||||
|
@ -115,7 +117,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@Override
|
||||
public List<UsbSerialPort> getPorts() {
|
||||
return Collections.singletonList(mPort);
|
||||
return mPorts;
|
||||
}
|
||||
|
||||
private class FtdiSerialPort extends CommonUsbSerialPort {
|
||||
|
@ -163,7 +165,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
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_RX = 1; // RX @ FTDI device = write @ usb-serial-for-android library
|
||||
private static final int SIO_RESET_PURGE_TX = 2;
|
||||
|
||||
public static final int FTDI_DEVICE_OUT_REQTYPE =
|
||||
|
@ -181,16 +183,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
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;
|
||||
private int mIndex = 0;
|
||||
|
||||
public FtdiSerialPort(UsbDevice device, int portNumber) {
|
||||
super(device, portNumber);
|
||||
|
@ -210,10 +203,10 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
* @return The number of payload bytes
|
||||
*/
|
||||
private final int filterStatusBytes(byte[] src, byte[] dest, int totalBytesRead, int maxPacketSize) {
|
||||
final int packetsCount = totalBytesRead / maxPacketSize + (totalBytesRead % maxPacketSize == 0 ? 0 : 1);
|
||||
final int packetsCount = (totalBytesRead + maxPacketSize -1 )/ maxPacketSize;
|
||||
for (int packetIdx = 0; packetIdx < packetsCount; ++packetIdx) {
|
||||
final int count = (packetIdx == (packetsCount - 1))
|
||||
? (totalBytesRead % maxPacketSize) - MODEM_STATUS_HEADER_LENGTH
|
||||
? totalBytesRead - packetIdx * maxPacketSize - MODEM_STATUS_HEADER_LENGTH
|
||||
: maxPacketSize - MODEM_STATUS_HEADER_LENGTH;
|
||||
if (count > 0) {
|
||||
System.arraycopy(src,
|
||||
|
@ -228,14 +221,21 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
// TODO(mikey): autodetect.
|
||||
mType = DeviceType.TYPE_R;
|
||||
if(mDevice.getInterfaceCount() > 1) {
|
||||
mIndex = mPortNumber + 1;
|
||||
if (mDevice.getInterfaceCount() == 2)
|
||||
mType = DeviceType.TYPE_2232H;
|
||||
if (mDevice.getInterfaceCount() == 4)
|
||||
mType = DeviceType.TYPE_4232H;
|
||||
}
|
||||
|
||||
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
|
||||
SIO_RESET_SIO, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
SIO_RESET_SIO, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
if (result != 0) {
|
||||
throw new IOException("Reset failed: result=" + result);
|
||||
}
|
||||
|
||||
// TODO(mikey): autodetect.
|
||||
mType = DeviceType.TYPE_R;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,12 +247,10 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
boolean opened = false;
|
||||
try {
|
||||
for (int i = 0; i < mDevice.getInterfaceCount(); i++) {
|
||||
if (connection.claimInterface(mDevice.getInterface(i), true)) {
|
||||
Log.d(TAG, "claimInterface " + i + " SUCCESS");
|
||||
} else {
|
||||
throw new IOException("Error claiming interface " + i);
|
||||
}
|
||||
if (connection.claimInterface(mDevice.getInterface(mPortNumber), true)) {
|
||||
Log.d(TAG, "claimInterface " + mPortNumber + " SUCCESS");
|
||||
} else {
|
||||
throw new IOException("Error claiming interface " + mPortNumber);
|
||||
}
|
||||
reset();
|
||||
opened = true;
|
||||
|
@ -278,20 +276,12 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@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();
|
||||
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(0);
|
||||
final UsbRequest request = new UsbRequest();
|
||||
final ByteBuffer buf = ByteBuffer.wrap(dest);
|
||||
try {
|
||||
request.initialize(mConnection, endpoint);
|
||||
|
||||
final ByteBuffer buf = ByteBuffer.wrap(dest);
|
||||
if (!request.queue(buf, readAmt)) {
|
||||
if (!request.queue(buf, dest.length)) {
|
||||
throw new IOException("Error queueing request.");
|
||||
}
|
||||
|
||||
|
@ -299,34 +289,21 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
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());
|
||||
}
|
||||
} finally {
|
||||
request.close();
|
||||
}
|
||||
|
||||
final int totalBytesRead = buf.position();
|
||||
if (totalBytesRead < MODEM_STATUS_HEADER_LENGTH) {
|
||||
throw new IOException("Expected at least " + MODEM_STATUS_HEADER_LENGTH + " bytes");
|
||||
}
|
||||
|
||||
return filterStatusBytes(dest, dest, totalBytesRead, endpoint.getMaxPacketSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(byte[] src, int timeoutMillis) throws IOException {
|
||||
final UsbEndpoint endpoint = mDevice.getInterface(0).getEndpoint(1);
|
||||
final UsbEndpoint endpoint = mDevice.getInterface(mPortNumber).getEndpoint(1);
|
||||
int offset = 0;
|
||||
|
||||
while (offset < src.length) {
|
||||
|
@ -379,7 +356,18 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
throws IOException {
|
||||
setBaudRate(baudRate);
|
||||
|
||||
int config = dataBits;
|
||||
int config = 0;
|
||||
switch (dataBits) {
|
||||
case DATABITS_5:
|
||||
case DATABITS_6:
|
||||
throw new IllegalArgumentException("Unsupported dataBits value: " + dataBits);
|
||||
case DATABITS_7:
|
||||
case DATABITS_8:
|
||||
config |= dataBits;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown dataBits value: " + dataBits);
|
||||
}
|
||||
|
||||
switch (parity) {
|
||||
case PARITY_NONE:
|
||||
|
@ -406,8 +394,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
config |= (0x00 << 11);
|
||||
break;
|
||||
case STOPBITS_1_5:
|
||||
config |= (0x01 << 11);
|
||||
break;
|
||||
throw new IllegalArgumentException("Unsupported stopBits value: 1.5");
|
||||
case STOPBITS_2:
|
||||
config |= (0x02 << 11);
|
||||
break;
|
||||
|
@ -416,7 +403,7 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE,
|
||||
SIO_SET_DATA_REQUEST, config, 0 /* index */,
|
||||
SIO_SET_DATA_REQUEST, config, mIndex,
|
||||
null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
if (result != 0) {
|
||||
throw new IOException("Setting parameters failed: result=" + result);
|
||||
|
@ -496,9 +483,8 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
long index;
|
||||
if (mType == DeviceType.TYPE_2232C || mType == DeviceType.TYPE_2232H
|
||||
|| mType == DeviceType.TYPE_4232H) {
|
||||
index = (encodedDivisor >> 8) & 0xffff;
|
||||
index &= 0xFF00;
|
||||
index |= 0 /* TODO mIndex */;
|
||||
index = (encodedDivisor >> 8) & 0xff00;
|
||||
index |= mIndex;
|
||||
} else {
|
||||
index = (encodedDivisor >> 16) & 0xffff;
|
||||
}
|
||||
|
@ -548,20 +534,20 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
|
||||
if (purgeReadBuffers) {
|
||||
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
||||
if (purgeWriteBuffers) {
|
||||
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
|
||||
SIO_RESET_PURGE_RX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
SIO_RESET_PURGE_RX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
if (result != 0) {
|
||||
throw new IOException("Flushing RX failed: result=" + result);
|
||||
throw new IOException("purge write buffer failed: result=" + result);
|
||||
}
|
||||
}
|
||||
|
||||
if (purgeWriteBuffers) {
|
||||
if (purgeReadBuffers) {
|
||||
int result = mConnection.controlTransfer(FTDI_DEVICE_OUT_REQTYPE, SIO_RESET_REQUEST,
|
||||
SIO_RESET_PURGE_TX, 0 /* index */, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
SIO_RESET_PURGE_TX, mIndex, null, 0, USB_WRITE_TIMEOUT_MILLIS);
|
||||
if (result != 0) {
|
||||
throw new IOException("Flushing RX failed: result=" + result);
|
||||
throw new IOException("purge read buffer failed: result=" + result);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -570,9 +556,12 @@ public class FtdiSerialDriver implements UsbSerialDriver {
|
|||
|
||||
public static Map<Integer, int[]> getSupportedDevices() {
|
||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_FTDI),
|
||||
supportedDevices.put(UsbId.VENDOR_FTDI,
|
||||
new int[] {
|
||||
UsbId.FTDI_FT232R,
|
||||
UsbId.FTDI_FT232H,
|
||||
UsbId.FTDI_FT2232H,
|
||||
UsbId.FTDI_FT4232H,
|
||||
UsbId.FTDI_FT231X,
|
||||
});
|
||||
return supportedDevices;
|
||||
|
|
|
@ -32,10 +32,12 @@ 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.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -86,7 +88,7 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||
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_RX_REQUEST = 0x08; // RX @ Prolific device = write @ usb-serial-for-android library
|
||||
private static final int FLUSH_TX_REQUEST = 0x09;
|
||||
|
||||
private static final int SET_LINE_REQUEST = 0x20;
|
||||
|
@ -368,15 +370,28 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||
|
||||
@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) {
|
||||
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;
|
||||
}
|
||||
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
|
||||
return numBytesRead;
|
||||
} finally {
|
||||
request.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,22 +553,22 @@ public class ProlificSerialDriver implements UsbSerialDriver {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean purgeHwBuffers(boolean purgeReadBuffers, boolean purgeWriteBuffers) throws IOException {
|
||||
if (purgeReadBuffers) {
|
||||
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException {
|
||||
if (purgeWriteBuffers) {
|
||||
vendorOut(FLUSH_RX_REQUEST, 0, null);
|
||||
}
|
||||
|
||||
if (purgeWriteBuffers) {
|
||||
if (purgeReadBuffers) {
|
||||
vendorOut(FLUSH_TX_REQUEST, 0, null);
|
||||
}
|
||||
|
||||
return purgeReadBuffers || purgeWriteBuffers;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<Integer, int[]> getSupportedDevices() {
|
||||
final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>();
|
||||
supportedDevices.put(Integer.valueOf(UsbId.VENDOR_PROLIFIC),
|
||||
supportedDevices.put(UsbId.VENDOR_PROLIFIC,
|
||||
new int[] { UsbId.PROLIFIC_PL2303, });
|
||||
return supportedDevices;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ public final class UsbId {
|
|||
|
||||
public static final int VENDOR_FTDI = 0x0403;
|
||||
public static final int FTDI_FT232R = 0x6001;
|
||||
public static final int FTDI_FT2232H = 0x6010;
|
||||
public static final int FTDI_FT4232H = 0x6011;
|
||||
public static final int FTDI_FT232H = 0x6014;
|
||||
public static final int FTDI_FT231X = 0x6015;
|
||||
|
||||
public static final int VENDOR_ATMEL = 0x03EB;
|
||||
|
@ -68,6 +71,10 @@ public final class UsbId {
|
|||
public static final int VENDOR_QINHENG = 0x1a86;
|
||||
public static final int QINHENG_HL340 = 0x7523;
|
||||
|
||||
// at www.linux-usb.org/usb.ids listed for NXP/LPC1768, but all processors supported by ARM mbed DAPLink firmware report these ids
|
||||
public static final int VENDOR_ARM = 0x0d28;
|
||||
public static final int ARM_MBED = 0x0204;
|
||||
|
||||
private UsbId() {
|
||||
throw new IllegalAccessError("Non-instantiable class.");
|
||||
}
|
||||
|
|
|
@ -216,13 +216,13 @@ public interface UsbSerialPort {
|
|||
public void setRTS(boolean value) throws IOException;
|
||||
|
||||
/**
|
||||
* Flush non-transmitted output data and / or non-read input data
|
||||
* @param flushRX {@code true} to flush non-transmitted output data
|
||||
* @param flushTX {@code true} to flush non-read input data
|
||||
* purge non-transmitted output data and / or non-read input data
|
||||
* @param purgeWriteBuffers {@code true} to discard non-transmitted output data
|
||||
* @param purgeReadBuffers {@code true} to discard non-read input data
|
||||
* @return {@code true} if the operation was successful, or
|
||||
* {@code false} if the operation is not supported by the driver or device
|
||||
* @throws IOException if an error occurred during flush
|
||||
*/
|
||||
public boolean purgeHwBuffers(boolean flushRX, boolean flushTX) throws IOException;
|
||||
public boolean purgeHwBuffers(boolean purgeWriteBuffers, boolean purgeReadBuffers) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,46 +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.
|
||||
*/
|
||||
|
||||
package com.hoho.android.usbserial.driver;
|
||||
|
||||
/**
|
||||
* Generic unchecked exception for the usbserial package.
|
||||
*
|
||||
* @author mike wakerly (opensource@hoho.com)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class UsbSerialRuntimeException extends RuntimeException {
|
||||
|
||||
public UsbSerialRuntimeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UsbSerialRuntimeException(String detailMessage, Throwable throwable) {
|
||||
super(detailMessage, throwable);
|
||||
}
|
||||
|
||||
public UsbSerialRuntimeException(String detailMessage) {
|
||||
super(detailMessage);
|
||||
}
|
||||
|
||||
public UsbSerialRuntimeException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
|
||||
}
|
|
@ -50,7 +50,7 @@ public class SerialInputOutputManager implements Runnable {
|
|||
// Synchronized by 'mWriteBuffer'
|
||||
private final ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ);
|
||||
|
||||
private enum State {
|
||||
public enum State {
|
||||
STOPPED,
|
||||
RUNNING,
|
||||
STOPPING
|
||||
|
@ -111,7 +111,7 @@ public class SerialInputOutputManager implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized State getState() {
|
||||
public synchronized State getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,6 @@ public class SerialInputOutputManager implements Runnable {
|
|||
* called, or until a driver exception is raised.
|
||||
*
|
||||
* NOTE(mikey): Uses inefficient read/write-with-timeout.
|
||||
* TODO(mikey): Read asynchronously with {@link UsbRequest#queue(ByteBuffer, int)}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
Loading…
Reference in New Issue