Porównaj commity
76 Commity
Autor | SHA1 | Data |
---|---|---|
green-green-avk | 7ad6c9f688 | |
green-green-avk | 9b915b2f84 | |
green-green-avk | 7fe4ce6e50 | |
alex | 94838280cd | |
green-green-avk | 7fff8b6d5c | |
green-green-avk | 4353bf1f4f | |
alex | f0dda6635c | |
green-green-avk | f537d13ede | |
green-green-avk | 3e0fe32f16 | |
Rob Riggs | 6987b48e14 | |
Felipe Herranz | 319cb9de68 | |
Changwoo Ryu | 37eac8d477 | |
Felipe Herranz | 828809f874 | |
Felipe Herranz | 08ef5bbb3f | |
Felipe Herranz | 85c69b540d | |
Felipe Herranz | b967da3c54 | |
Mickael Storck | f4889f03cb | |
Felipe Herranz | d0232ed59a | |
Felipe Herranz | 538e2e0483 | |
Felipe Herranz | 90396ab436 | |
Felipe Herranz | fdfb9f1053 | |
Felipe Herranz | 1e68f744c5 | |
Felipe Herranz | 58bc4a47c3 | |
Felipe Herranz | f0898c3c1d | |
Felipe Herranz | 2f4a4de99c | |
Felipe Herranz | 10d1088228 | |
Felipe Herranz | 4e74b05689 | |
Felipe Herranz | e9eb771541 | |
Felipe Herranz | 9f32a3b7e9 | |
Sven Van Asbroeck | 6180eb497c | |
Charles Julian Knight | f52c67a134 | |
Felipe Herranz | 91a5368445 | |
Felipe Herranz | ffe964f672 | |
Felipe Herranz | 8261ea855c | |
jani | c0c5a2848c | |
Felipe Herranz | 3465c5041e | |
Felipe Herranz | 1823f2b167 | |
Felipe Herranz | 1e672fcb96 | |
Felipe Herranz | bef34df377 | |
xiongyi | 33fed5e09c | |
Felipe Herranz | b6aef50017 | |
Felipe Herranz | 217d651f68 | |
Felipe Herranz | f07bb50b28 | |
Felipe Herranz | ca5379f9c4 | |
Felipe Herranz | 5eddda99e9 | |
Felipe Herranz | 41ced7c2a7 | |
Felipe Herranz | 2afa82ddc3 | |
Felipe Herranz | 8a0d9c8850 | |
Felipe Herranz | 9c51f4c19b | |
Felipe Herranz | 4108a6905e | |
Felipe Herranz | ac88abca1a | |
sonbuidev | 001e745a4a | |
phuongnam0907 | 5ec307966a | |
Felipe Herranz | 3e889f646f | |
Felipe Herranz | 9458b7f136 | |
Felipe Herranz | dcc5063197 | |
Felipe Herranz | 566c20f2b3 | |
Felipe Herranz | aad56b768b | |
Felipe Herranz | da875752b1 | |
Felipe Herranz | 1d7d0d9625 | |
Felipe Herranz | 324ec77db6 | |
Felipe Herranz | 1e4bd132cc | |
Felipe Herranz | 2487b609c5 | |
Raul Bache | b5f7699a52 | |
Felipe Herranz | d369c0d31d | |
Felipe Herranz | b5dd43e5d2 | |
Felipe Herranz | 47f606396c | |
Felipe Herranz | bd350b618e | |
Felipe Herranz | 121598728b | |
Felipe Herranz | 203a65eb54 | |
Raul Bache | b98ea3278d | |
Felipe Herranz | f30817c30f | |
Felipe Herranz | ed8cf6208e | |
Felipe Herranz | d9b790f611 | |
Felipe Herranz | 7ae5df917f | |
Felipe Herranz | 901590bd2e |
|
@ -28,3 +28,9 @@ local.properties
|
|||
# Gradle
|
||||
build/
|
||||
.gradle
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
|
26
CHANGELOG.md
|
@ -1,7 +1,31 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
Release 6.0.2
|
||||
Release 6.1.0
|
||||
--------------------------------------
|
||||
- Added 1228800 and 2000000 baud rates to CH34xx driver.
|
||||
- Microchip pid/vid correclty determined.
|
||||
- FTDI sync method back to previous implementation.
|
||||
- setBreak method implemented in CP210x devices.
|
||||
- Added chunked stream methods.
|
||||
|
||||
Release 6.0.6
|
||||
--------------------------------------
|
||||
- Added custom baud rates in FTDI devices.
|
||||
- Added setBreak method. Currently only working in FTDI devices.
|
||||
|
||||
Release 6.0.5
|
||||
--------------------------------------
|
||||
- Solved issue with CDC.
|
||||
- Added new pair of VID/PID pairs for CP2102.
|
||||
- Threads closing in a safer way.
|
||||
|
||||
Release 6.0.4
|
||||
--------------------------------------
|
||||
- Proguard rules.
|
||||
- FTDI driver improved again.
|
||||
|
||||
Release 6.0.3
|
||||
--------------------------------------
|
||||
- VID/PID pairs are sorted and searched in a faster way.
|
||||
- FTDI driver improved.
|
||||
|
|
|
@ -9,7 +9,12 @@ UsbSerial wiki available. Read it first
|
|||
[**Synchronous api**](https://github.com/felHR85/UsbSerial/wiki/5.-Synchronous-api)\
|
||||
[**InputStream and OutputStream I/O**](https://github.com/felHR85/UsbSerial/wiki/6.-InputStream-and-OutputStream-I-O)\
|
||||
[**Multiple Serial ports**](https://github.com/felHR85/UsbSerial/wiki/7.-Multiple-Serial-ports)\
|
||||
[**Projects using UsbSerial**](https://github.com/felHR85/UsbSerial/wiki/8.-Projects-using-UsbSerial)
|
||||
[**Projects using UsbSerial**](https://github.com/felHR85/UsbSerial/wiki/8.-Projects-using-UsbSerial)\
|
||||
[**Debugging over Wifi**](https://github.com/felHR85/UsbSerial/wiki/9.-Debugging-over-Wifi)\
|
||||
[**UsbSerial video tutorials**](https://github.com/felHR85/UsbSerial/wiki/10.-UsbSerial-video-tutorials)
|
||||
|
||||
[I am looking for collaborators to keep this project updated](https://github.com/felHR85/UsbSerial/issues/313)
|
||||
--------------------------------------
|
||||
|
||||
Support UsbSerial
|
||||
--------------------------------------
|
||||
|
@ -192,7 +197,7 @@ Then add the dependency to your module's build.gradle:
|
|||
|
||||
/app/build.gradle
|
||||
```groovy
|
||||
implementation 'com.github.felHR85:UsbSerial:6.0.3'
|
||||
implementation 'com.github.felHR85:UsbSerial:6.1.0'
|
||||
```
|
||||
|
||||
TO-DO
|
||||
|
|
|
@ -5,7 +5,7 @@ Releasing
|
|||
2. Update the `README.md` with the new version and update `CHANGELOG.md`
|
||||
3. `./gradlew clean build`
|
||||
4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version)
|
||||
5. `git tag -a X.Y.Z -m "Version X.Y.Z"` -m "Changelog message 1" - m "Changelog message 2" -m "Changelog message 3"
|
||||
5. `git tag -a X.Y.Z -m "Version X.Y.Z"` `-m "Changelog message 1"` `-m "Changelog message 2"` `-m "Changelog message 3"`
|
||||
6. `git push && git push --tags`
|
||||
|
||||
*Note:* To get the changelog messages from the commit history, issue
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.0'
|
||||
classpath 'com.android.tools.build:gradle:4.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
VERSION_NAME=6.0.3
|
||||
VERSION_NAME=6.1.0
|
||||
VERSION_CODE=1
|
||||
ANDROID_BUILD_MIN_SDK_VERSION=12
|
||||
ANDROID_BUILD_TARGET_SDK_VERSION=27
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Tue Mar 27 00:15:43 CEST 2018
|
||||
#Mon Dec 14 15:18:57 PST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
UsbSerial Integration Tests
|
||||
===========================
|
||||
For the purpose of helping people contributing to UsbSerial a little set of integration tests have been added. It consists in two parts.
|
||||
- Python script integration.py that sends a series packets (1kb, 2kb, 8kb, 64kb and 128kb) and validates that those packets are received back correctly.
|
||||
- Integration Android app that implements UsbSerial and just receives and sends back the packets sent by the python script.
|
||||
|
||||
Requirements
|
||||
--------------------------------------
|
||||
- Windows/OSX/Linux with Python 3 installed
|
||||
- [PySerial](https://pypi.org/project/pyserial/)
|
||||
- Android phone with Android 3.1 and with USB OTG capabilities
|
||||
|
||||
Steps
|
||||
--------------------------------------
|
||||
Let's say we want to test UsbSerial transmitting at 115200 bauds and our PC port is /dev/ttyUSB0
|
||||
- [Modify UsbService in Integration app to 115200 bauds](https://github.com/felHR85/UsbSerial/blob/integration_tests/integrationapp/src/main/java/com/felhr/integrationapp/UsbService.java#L61).
|
||||
- Compile and install Integration app on your device.
|
||||
- Connect your phone to a serial device at one end and your PC at the other end.
|
||||
- Run python integration.py /dev/ttyUSB0 115200
|
||||
|
||||
Other Scripts
|
||||
--------------------------------------
|
||||
- send_packet.py (python send_packet.py /dev/ttyUSB0 1024 115200)
|
||||
- validate_serial_tx.py (python validate_serial_tx.py /dev/ttyUSB0 1024 115200)
|
|
@ -0,0 +1,34 @@
|
|||
# UsbSerial test: Integration test
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
class style():
|
||||
RED = lambda x: '\033[31m' + str(x)
|
||||
GREEN = lambda x: '\033[32m' + str(x)
|
||||
BLUE = lambda x: '\033[34m' + str(x)
|
||||
RESET = lambda x: '\033[0m' + str(x)
|
||||
|
||||
port = sys.argv[1]
|
||||
speed = sys.argv[2]
|
||||
|
||||
test_sizes = [1024, 2048, 16384, 65535, 131072]
|
||||
|
||||
for i in range(0,5):
|
||||
comm = serial.Serial(port, int(speed))
|
||||
print("Creating " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_tx = os.urandom(test_sizes[i])
|
||||
print("Sending buffer of " + str(test_sizes[i]) + " bytes")
|
||||
comm.write(data_tx)
|
||||
print("Receiving " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_rx = comm.read(test_sizes[i])
|
||||
|
||||
if data_tx == data_rx:
|
||||
print(style.GREEN("Success: " + str(test_sizes[i]) + " bytes buffer was transmitted correctly"))
|
||||
else:
|
||||
print(style.RED("Error: " + str(test_sizes[i]) + " bytes buffer was not transmitted correctly"))
|
||||
print(style.RESET(""))
|
|
@ -0,0 +1,34 @@
|
|||
# UsbSerial test: Integration test
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
class style():
|
||||
RED = lambda x: '\033[31m' + str(x)
|
||||
GREEN = lambda x: '\033[32m' + str(x)
|
||||
BLUE = lambda x: '\033[34m' + str(x)
|
||||
RESET = lambda x: '\033[0m' + str(x)
|
||||
|
||||
port = sys.argv[1]
|
||||
speed = sys.argv[2]
|
||||
|
||||
test_sizes = [1024, 2048, 16384]
|
||||
|
||||
for i in range(0,3):
|
||||
comm = serial.Serial(port, int(speed))
|
||||
print("Creating " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_tx = os.urandom(test_sizes[i])
|
||||
print("Sending buffer of " + str(test_sizes[i]) + " bytes")
|
||||
comm.write(data_tx)
|
||||
print("Receiving " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_rx = comm.read(test_sizes[i])
|
||||
|
||||
if data_tx == data_rx:
|
||||
print(style.GREEN("Success: " + str(test_sizes[i]) + " bytes buffer was transmitted correctly"))
|
||||
else:
|
||||
print(style.RED("Error: " + str(test_sizes[i]) + " bytes buffer was not transmitted correctly"))
|
||||
print(style.RESET(""))
|
|
@ -0,0 +1,21 @@
|
|||
# UsbSerial test: Sending single packet
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# size in bytes (eg 1024)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
port = sys.argv[1]
|
||||
size = sys.argv[2]
|
||||
speed = sys.argv[3]
|
||||
|
||||
comm = serial.Serial(port, int(speed))
|
||||
|
||||
data_tx = os.urandom(int(size))
|
||||
|
||||
bytes_sent = comm.write(data_tx)
|
||||
|
||||
print(str(bytes_sent))
|
|
@ -0,0 +1,35 @@
|
|||
#!bin/bash
|
||||
|
||||
# UsbSerial
|
||||
#
|
||||
# This test generates a number of files specified by the user and send them through the serial port.
|
||||
#
|
||||
# args:
|
||||
# -p: serial port (ttyUSB0, ttyUSB1..)
|
||||
# -b: baud rate
|
||||
# -t: number of times this test will be repeated
|
||||
# -s: size of the random files generated for testing purposes
|
||||
|
||||
while getopts p:t:s:b: OPTION;
|
||||
do
|
||||
case $OPTION
|
||||
in
|
||||
p) PORT=$OPTARG;;
|
||||
t) TIMES=$OPTARG;;
|
||||
s) SIZE=$OPTARG;;
|
||||
b) BAUD=$OPTARG;;
|
||||
esac
|
||||
done
|
||||
|
||||
stty -F $PORT $BAUD
|
||||
|
||||
for i in $(seq 1 $TIMES);
|
||||
do
|
||||
dd if=/dev/urandom of=$i bs=$SIZE count=1 status=none
|
||||
echo "Packet $i of $SIZE was created"
|
||||
cat $i > $PORT
|
||||
echo "Packet $i of $SIZE was sent"
|
||||
|
||||
done
|
||||
|
||||
rm [0-9]*
|
|
@ -0,0 +1,26 @@
|
|||
# UsbSerial test: Validate single packet
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# size in bytes (eg 1024)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
port = sys.argv[1]
|
||||
size = sys.argv[2]
|
||||
speed = sys.argv[3]
|
||||
|
||||
comm = serial.Serial(port, int(speed))
|
||||
|
||||
data_tx = os.urandom(int(size))
|
||||
|
||||
comm.write(data_tx)
|
||||
|
||||
data_rx = comm.read(int(size))
|
||||
|
||||
if data_tx == data_rx:
|
||||
print("Success: Data was transmitted correctly")
|
||||
else:
|
||||
print("Error: Data was not transmitted")
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,39 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.felhr.integrationapp"
|
||||
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
|
||||
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
|
||||
versionName project.VERSION_NAME
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
encoding "UTF-8"
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:support-v4:23.1.1'
|
||||
implementation 'com.android.support:appcompat-v7:23.1.1'
|
||||
implementation 'com.android.support:design:23.1.1'
|
||||
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
implementation 'com.squareup.okio:okio:2.1.0'
|
||||
|
||||
implementation project(':usbserial')
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.felhr.integrationapp", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.felhr.integrationapp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-feature android:name="android.hardware.usb.host"
|
||||
android:required="true"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service
|
||||
android:name="com.felhr.integrationapp.UsbService"
|
||||
android:enabled="true">
|
||||
</service>
|
||||
<service
|
||||
android:name="com.felhr.integrationapp.UsbSyncService"
|
||||
android:enabled="true">
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_1;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_2;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_3;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_4;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_5;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private static final int MODE = 0; // 0: Async, 1: Sync, 2: Streams
|
||||
|
||||
/*
|
||||
* Notifications from UsbService will be received here.
|
||||
*/
|
||||
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
switch (intent.getAction()) {
|
||||
case UsbService.ACTION_USB_PERMISSION_GRANTED: // USB PERMISSION GRANTED
|
||||
Toast.makeText(context, "USB Ready", Toast.LENGTH_SHORT).show();
|
||||
statusText.setText("USB connected. Run Python tests");
|
||||
break;
|
||||
case UsbService.ACTION_USB_PERMISSION_NOT_GRANTED: // USB PERMISSION NOT GRANTED
|
||||
Toast.makeText(context, "USB Permission not granted", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_NO_USB: // NO USB CONNECTED
|
||||
Toast.makeText(context, "No USB connected", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_USB_DISCONNECTED: // USB DISCONNECTED
|
||||
Toast.makeText(context, "USB disconnected", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_USB_NOT_SUPPORTED: // USB NOT SUPPORTED
|
||||
Toast.makeText(context, "USB device not supported", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
private UsbService usbService;
|
||||
private UsbSyncService usbSyncService;
|
||||
private TextView test1, test2, test3, test4, test5;
|
||||
private TextView statusText;
|
||||
private MyHandler mHandler;
|
||||
|
||||
private final ServiceConnection usbConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
|
||||
usbService = ((UsbService.UsbBinder) arg1).getService();
|
||||
usbService.setHandler(mHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
usbService = null;
|
||||
}
|
||||
};
|
||||
|
||||
private final ServiceConnection usbSyncConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
|
||||
usbSyncService = ((UsbSyncService.UsbBinder) arg1).getService();
|
||||
usbSyncService.setHandler(mHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
usbSyncService = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
test1 = findViewById(R.id.test_1_result);
|
||||
test2 = findViewById(R.id.test_2_result);
|
||||
test3 = findViewById(R.id.test_3_result);
|
||||
test4 = findViewById(R.id.test_4_result);
|
||||
test5 = findViewById(R.id.test_5_result);
|
||||
statusText = findViewById(R.id.status);
|
||||
mHandler = new MyHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setFilters(); // Start listening notifications from UsbService
|
||||
Toast.makeText(this, "Mode: " + String.valueOf(MODE), Toast.LENGTH_LONG).show();
|
||||
if (MODE == 0) {
|
||||
startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
|
||||
}else if (MODE == 1) {
|
||||
startService(UsbSyncService.class, usbSyncConnection, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mUsbReceiver);
|
||||
if(MODE == 0) {
|
||||
unbindService(usbConnection);
|
||||
}else{
|
||||
unbindService(usbSyncConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {
|
||||
if (!UsbService.SERVICE_CONNECTED) {
|
||||
Intent startService = new Intent(this, service);
|
||||
if (extras != null && !extras.isEmpty()) {
|
||||
Set<String> keys = extras.keySet();
|
||||
for (String key : keys) {
|
||||
String extra = extras.getString(key);
|
||||
startService.putExtra(key, extra);
|
||||
}
|
||||
}
|
||||
startService(startService);
|
||||
}
|
||||
Intent bindingIntent = new Intent(this, service);
|
||||
bindService(bindingIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
private void setFilters() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(UsbService.ACTION_USB_PERMISSION_GRANTED);
|
||||
filter.addAction(UsbService.ACTION_NO_USB);
|
||||
filter.addAction(UsbService.ACTION_USB_DISCONNECTED);
|
||||
filter.addAction(UsbService.ACTION_USB_NOT_SUPPORTED);
|
||||
filter.addAction(UsbService.ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
registerReceiver(mUsbReceiver, filter);
|
||||
}
|
||||
|
||||
private void resetTestTextViews(){
|
||||
test1.setText("TEST1: Not Passed");
|
||||
test2.setText("TEST2: Not Passed");
|
||||
test3.setText("TEST3: Not Passed");
|
||||
test4.setText("TEST4: Not Passed");
|
||||
test5.setText("TEST5: Not Passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* This handler will be passed to UsbService. Data received from serial port is displayed through this handler
|
||||
*/
|
||||
private static class MyHandler extends Handler {
|
||||
private final WeakReference<MainActivity> mActivity;
|
||||
|
||||
public MyHandler(MainActivity activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
String data = (String) msg.obj;
|
||||
switch (msg.what) {
|
||||
case MESSAGE_TEST_1:
|
||||
mActivity.get().test1.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_2:
|
||||
mActivity.get().test2.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_3:
|
||||
mActivity.get().test3.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_4:
|
||||
mActivity.get().test4.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_5:
|
||||
mActivity.get().test5.setText(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
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.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.felhr.usbserial.CDCSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okio.Buffer;
|
||||
|
||||
public class UsbService extends Service {
|
||||
|
||||
public static final String TAG = "UsbService";
|
||||
|
||||
private static final int SIZE_TEST_1 = 1024;
|
||||
private static final int SIZE_TEST_2 = 2048;
|
||||
private static final int SIZE_TEST_3 = 16384;
|
||||
private static final int SIZE_TEST_4 = 65535;
|
||||
private static final int SIZE_TEST_5 = 131072;
|
||||
|
||||
private static final String TEST_1 = "test1";
|
||||
private static final String TEST_2 = "test2";
|
||||
private static final String TEST_3 = "test3";
|
||||
private static final String TEST_4 = "test4";
|
||||
private static final String TEST_5 = "test5";
|
||||
|
||||
|
||||
public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
|
||||
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
|
||||
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
|
||||
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
|
||||
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
|
||||
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
|
||||
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
|
||||
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
|
||||
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
|
||||
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
|
||||
public static final int MESSAGE_TEST_1 = 0;
|
||||
public static final int MESSAGE_TEST_2 = 1;
|
||||
public static final int MESSAGE_TEST_3 = 2;
|
||||
public static final int MESSAGE_TEST_4 = 3;
|
||||
public static final int MESSAGE_TEST_5 = 4;
|
||||
public static final int CTS_CHANGE = 1;
|
||||
public static final int DSR_CHANGE = 2;
|
||||
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
|
||||
private static final int BAUD_RATE = 115200; // BaudRate. Change this value if you need
|
||||
public static boolean SERVICE_CONNECTED = false;
|
||||
|
||||
private IBinder binder = new UsbBinder();
|
||||
|
||||
private Context context;
|
||||
private Handler mHandler;
|
||||
private UsbManager usbManager;
|
||||
private UsbDevice device;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbSerialDevice serialPort;
|
||||
|
||||
private Buffer buffer = new Buffer();
|
||||
private String mode;
|
||||
|
||||
private boolean serialPortConnected;
|
||||
|
||||
|
||||
private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
|
||||
@Override
|
||||
public void onReceivedData(byte[] arg0) {
|
||||
buffer.write(arg0);
|
||||
if(mode.equals(TEST_1)){
|
||||
if(buffer.size() == SIZE_TEST_1){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_2;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_1, "Test 1Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_2)){
|
||||
if(buffer.size() == SIZE_TEST_2){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_3;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_2, "Test 2Kb completed correctly").sendToTarget();
|
||||
}
|
||||
|
||||
}else if(mode.equals(TEST_3)){
|
||||
if(buffer.size() == SIZE_TEST_3){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_4;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_3, "Test 16Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_4)){
|
||||
if(buffer.size() == SIZE_TEST_4){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_5;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_4, "Test 64Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_5)){
|
||||
if(buffer.size() == SIZE_TEST_5){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_1;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_5, "Test 128Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* State changes in the CTS line will be received here
|
||||
*/
|
||||
private UsbSerialInterface.UsbCTSCallback ctsCallback = new UsbSerialInterface.UsbCTSCallback() {
|
||||
@Override
|
||||
public void onCTSChanged(boolean state) {
|
||||
if(mHandler != null)
|
||||
mHandler.obtainMessage(CTS_CHANGE).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* State changes in the DSR line will be received here
|
||||
*/
|
||||
private UsbSerialInterface.UsbDSRCallback dsrCallback = new UsbSerialInterface.UsbDSRCallback() {
|
||||
@Override
|
||||
public void onDSRChanged(boolean state) {
|
||||
if(mHandler != null)
|
||||
mHandler.obtainMessage(DSR_CHANGE).sendToTarget();
|
||||
}
|
||||
};
|
||||
/*
|
||||
* Different notifications from OS will be received here (USB attached, detached, permission responses...)
|
||||
* About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
|
||||
*/
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent arg1) {
|
||||
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
|
||||
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
|
||||
if (granted) // User accepted our USB connection. Try to open the device as a serial port
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
connection = usbManager.openDevice(device);
|
||||
new ConnectionThread().start();
|
||||
} else // User not accepted our USB connection. Send an Intent to the Main Activity
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
}
|
||||
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
|
||||
if (!serialPortConnected)
|
||||
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
|
||||
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
|
||||
// Usb device was disconnected. send an intent to the Main Activity
|
||||
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
if (serialPortConnected) {
|
||||
serialPort.close();
|
||||
}
|
||||
serialPortConnected = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
|
||||
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.context = this;
|
||||
serialPortConnected = false;
|
||||
UsbService.SERVICE_CONNECTED = true;
|
||||
setFilter();
|
||||
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
findSerialPortDevice();
|
||||
mode = TEST_1;
|
||||
}
|
||||
|
||||
/* MUST READ about services
|
||||
* http://developer.android.com/guide/components/services.html
|
||||
* http://developer.android.com/guide/components/bound-services.html
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
serialPort.close();
|
||||
unregisterReceiver(usbReceiver);
|
||||
UsbService.SERVICE_CONNECTED = false;
|
||||
}
|
||||
|
||||
|
||||
public void setHandler(Handler mHandler) {
|
||||
this.mHandler = mHandler;
|
||||
}
|
||||
|
||||
private void findSerialPortDevice() {
|
||||
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
|
||||
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
|
||||
if (!usbDevices.isEmpty()) {
|
||||
|
||||
// first, dump the hashmap for diagnostic purposes
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
Log.d(TAG, String.format("USBDevice.HashMap (vid:pid) (%X:%X)-%b class:%X:%X name:%s",
|
||||
device.getVendorId(), device.getProductId(),
|
||||
UsbSerialDevice.isSupported(device),
|
||||
device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceName()));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
int deviceVID = device.getVendorId();
|
||||
int devicePID = device.getProductId();
|
||||
|
||||
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) && deviceVID != 0x5c6 && devicePID != 0x904c) {
|
||||
if (UsbSerialDevice.isSupported(device)) {
|
||||
// There is a supported device connected - request permission to access it.
|
||||
requestUserPermission();
|
||||
break;
|
||||
} else {
|
||||
connection = null;
|
||||
device = null;
|
||||
}
|
||||
}
|
||||
if (device==null) {
|
||||
// There are no USB devices connected (but usb host were listed). Send an intent to MainActivity.
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "findSerialPortDevice() usbManager returned empty device list." );
|
||||
// There is no USB devices connected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_USB_PERMISSION);
|
||||
filter.addAction(ACTION_USB_DETACHED);
|
||||
filter.addAction(ACTION_USB_ATTACHED);
|
||||
registerReceiver(usbReceiver, filter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request user permission. The response will be received in the BroadcastReceiver
|
||||
*/
|
||||
private void requestUserPermission() {
|
||||
Log.d(TAG, String.format("requestUserPermission(%X:%X)", device.getVendorId(), device.getProductId() ) );
|
||||
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
usbManager.requestPermission(device, mPendingIntent);
|
||||
}
|
||||
|
||||
public class UsbBinder extends Binder {
|
||||
public UsbService getService() {
|
||||
return UsbService.this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple thread to open a serial port.
|
||||
* Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
|
||||
*/
|
||||
private class ConnectionThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
|
||||
if (serialPort != null) {
|
||||
if (serialPort.open()) {
|
||||
serialPortConnected = true;
|
||||
serialPort.setBaudRate(BAUD_RATE);
|
||||
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
|
||||
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
|
||||
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
|
||||
/**
|
||||
* Current flow control Options:
|
||||
* UsbSerialInterface.FLOW_CONTROL_OFF
|
||||
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
|
||||
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
|
||||
*/
|
||||
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
|
||||
serialPort.read(mCallback);
|
||||
serialPort.getCTS(ctsCallback);
|
||||
serialPort.getDSR(dsrCallback);
|
||||
|
||||
//
|
||||
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
|
||||
// to be uploaded or not
|
||||
//Thread.sleep(2000); // sleep some. YMMV with different chips.
|
||||
|
||||
// Everything went as expected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_USB_READY);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
|
||||
// Send an Intent to Main Activity
|
||||
if (serialPort instanceof CDCSerialDevice) {
|
||||
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No driver for given device, even generic CDC driver could not be loaded
|
||||
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
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.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.felhr.usbserial.CDCSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okio.Buffer;
|
||||
|
||||
/**
|
||||
* Created by Felipe Herranz(felhr85@gmail.com) on 2019-07-04.
|
||||
*/
|
||||
public class UsbSyncService extends Service {
|
||||
|
||||
public static final String TAG = "UsbService";
|
||||
|
||||
private static final int SIZE_TEST_1 = 1024;
|
||||
private static final int SIZE_TEST_2 = 2048;
|
||||
private static final int SIZE_TEST_3 = 16384;
|
||||
|
||||
private static final String TEST_1 = "test1";
|
||||
private static final String TEST_2 = "test2";
|
||||
private static final String TEST_3 = "test3";
|
||||
private static final String TEST_4 = "test4";
|
||||
private static final String TEST_5 = "test5";
|
||||
|
||||
private static final int BUFFER_SYNC = 100;
|
||||
|
||||
|
||||
public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
|
||||
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
|
||||
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
|
||||
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
|
||||
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
|
||||
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
|
||||
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
|
||||
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
|
||||
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
|
||||
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
|
||||
public static final int MESSAGE_TEST_1 = 0;
|
||||
public static final int MESSAGE_TEST_2 = 1;
|
||||
public static final int MESSAGE_TEST_3 = 2;
|
||||
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
|
||||
private static final int BAUD_RATE = 115200; // BaudRate. Change this value if you need
|
||||
public static boolean SERVICE_CONNECTED = false;
|
||||
|
||||
private IBinder binder = new UsbSyncService.UsbBinder();
|
||||
|
||||
private Context context;
|
||||
private Handler mHandler;
|
||||
private UsbManager usbManager;
|
||||
private UsbDevice device;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbSerialDevice serialPort;
|
||||
|
||||
private Buffer buffer = new Buffer();
|
||||
private String mode;
|
||||
|
||||
private ReadThread readThread;
|
||||
|
||||
private boolean serialPortConnected;
|
||||
|
||||
/*
|
||||
* Different notifications from OS will be received here (USB attached, detached, permission responses...)
|
||||
* About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
|
||||
*/
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent arg1) {
|
||||
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
|
||||
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
|
||||
if (granted) // User accepted our USB connection. Try to open the device as a serial port
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
connection = usbManager.openDevice(device);
|
||||
new ConnectionThread().start();
|
||||
} else // User not accepted our USB connection. Send an Intent to the Main Activity
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
}
|
||||
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
|
||||
if (!serialPortConnected)
|
||||
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
|
||||
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
|
||||
// Usb device was disconnected. send an intent to the Main Activity
|
||||
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
if (serialPortConnected) {
|
||||
serialPort.syncClose();
|
||||
}
|
||||
serialPortConnected = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
|
||||
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.context = this;
|
||||
serialPortConnected = false;
|
||||
UsbService.SERVICE_CONNECTED = true;
|
||||
setFilter();
|
||||
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
findSerialPortDevice();
|
||||
mode = TEST_1;
|
||||
}
|
||||
|
||||
/* MUST READ about services
|
||||
* http://developer.android.com/guide/components/services.html
|
||||
* http://developer.android.com/guide/components/bound-services.html
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
serialPort.close();
|
||||
unregisterReceiver(usbReceiver);
|
||||
UsbService.SERVICE_CONNECTED = false;
|
||||
}
|
||||
|
||||
|
||||
public void setHandler(Handler mHandler) {
|
||||
this.mHandler = mHandler;
|
||||
}
|
||||
|
||||
private void findSerialPortDevice() {
|
||||
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
|
||||
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
|
||||
if (!usbDevices.isEmpty()) {
|
||||
|
||||
// first, dump the hashmap for diagnostic purposes
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
Log.d(TAG, String.format("USBDevice.HashMap (vid:pid) (%X:%X)-%b class:%X:%X name:%s",
|
||||
device.getVendorId(), device.getProductId(),
|
||||
UsbSerialDevice.isSupported(device),
|
||||
device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceName()));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
int deviceVID = device.getVendorId();
|
||||
int devicePID = device.getProductId();
|
||||
|
||||
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) && deviceVID != 0x5c6 && devicePID != 0x904c) {
|
||||
if (UsbSerialDevice.isSupported(device)) {
|
||||
// There is a supported device connected - request permission to access it.
|
||||
requestUserPermission();
|
||||
break;
|
||||
} else {
|
||||
connection = null;
|
||||
device = null;
|
||||
}
|
||||
}
|
||||
if (device==null) {
|
||||
// There are no USB devices connected (but usb host were listed). Send an intent to MainActivity.
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "findSerialPortDevice() usbManager returned empty device list." );
|
||||
// There is no USB devices connected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_USB_PERMISSION);
|
||||
filter.addAction(ACTION_USB_DETACHED);
|
||||
filter.addAction(ACTION_USB_ATTACHED);
|
||||
registerReceiver(usbReceiver, filter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request user permission. The response will be received in the BroadcastReceiver
|
||||
*/
|
||||
private void requestUserPermission() {
|
||||
Log.d(TAG, String.format("requestUserPermission(%X:%X)", device.getVendorId(), device.getProductId() ) );
|
||||
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
usbManager.requestPermission(device, mPendingIntent);
|
||||
}
|
||||
|
||||
public class UsbBinder extends Binder {
|
||||
public UsbSyncService getService() {
|
||||
return UsbSyncService.this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple thread to open a serial port.
|
||||
* Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
|
||||
*/
|
||||
private class ConnectionThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
|
||||
if (serialPort != null) {
|
||||
if (serialPort.syncOpen()) {
|
||||
serialPortConnected = true;
|
||||
serialPort.setBaudRate(BAUD_RATE);
|
||||
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
|
||||
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
|
||||
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
|
||||
/**
|
||||
* Current flow control Options:
|
||||
* UsbSerialInterface.FLOW_CONTROL_OFF
|
||||
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
|
||||
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
|
||||
*/
|
||||
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
|
||||
|
||||
//
|
||||
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
|
||||
// to be uploaded or not
|
||||
//Thread.sleep(2000); // sleep some. YMMV with different chips.
|
||||
|
||||
// Everything went as expected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_USB_READY);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
readThread = new ReadThread();
|
||||
readThread.start();
|
||||
} else {
|
||||
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
|
||||
// Send an Intent to Main Activity
|
||||
if (serialPort instanceof CDCSerialDevice) {
|
||||
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No driver for given device, even generic CDC driver could not be loaded
|
||||
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReadThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
while(true){
|
||||
byte[] tmpBuffer = new byte[16384];
|
||||
int n = serialPort.syncRead(tmpBuffer, 0);
|
||||
|
||||
if(n > 0) {
|
||||
buffer.write(tmpBuffer, 0, n);
|
||||
}
|
||||
|
||||
if(mode.equals(TEST_1)){
|
||||
if(buffer.size() == SIZE_TEST_1){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_2;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_1, "Test 1Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_2)){
|
||||
if(buffer.size() == SIZE_TEST_2){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_3;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_2, "Test 2Kb completed correctly").sendToTarget();
|
||||
}
|
||||
|
||||
}else if(mode.equals(TEST_3)){
|
||||
if(buffer.size() == SIZE_TEST_3){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_1;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_3, "Test 16Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<vector xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
</vector>
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Integration Tests"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_1_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST1: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_2_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST2: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_3_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST3: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_4_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST4: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_5_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST5: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Connect USB Device"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Po Szerokość: | Wysokość: | Rozmiar: 2.9 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 4.8 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 2.0 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 2.7 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 4.4 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 6.7 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 6.2 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 10 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 8.9 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">IntegrationApp</string>
|
||||
</resources>
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,17 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
#Arguments:
|
||||
# -v version eg 6.0.3
|
||||
# -m 6.0.3
|
||||
set -e
|
||||
|
||||
while getopts v:m: OPTION;
|
||||
do
|
||||
case $OPTION
|
||||
in
|
||||
v) VERSION=$OPTARG;;
|
||||
m) MESSAGE=$OPTARG;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Show error message if no version was provided
|
||||
if [[ -z ${VERSION} ]];
|
||||
then
|
||||
echo "UsbSerial: Error!! No version was provided"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show error message if no message was provided
|
||||
if [[ -z ${MESSAGE} ]];
|
||||
then
|
||||
echo "UsbSerial: Error!! No message was provided"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "UsbSerial: Starting Release $VERSION with commit message $MESSAGE"
|
||||
|
||||
VERSION_NAME="VERSION_NAME=$VERSION"
|
||||
|
||||
# Updating gradle.properties with version
|
||||
ex -sc '1d|x' gradle.properties
|
||||
ex -sc "1i|$VERSION_NAME" -cx gradle.properties
|
||||
|
||||
# Updating README file
|
||||
GRADLE_LINE="implementation 'com.github.felHR85:UsbSerial:${VERSION}'"
|
||||
LINE=$(cat README.md | grep -nr implementation\ \'com.github.felHR85:UsbSerial: | awk -F ":" '{print $2}')
|
||||
ex -sc "${LINE}d|x" README.md
|
||||
ex -sc "${LINE}i|$GRADLE_LINE" -cx README.md
|
||||
|
||||
# Gradle clean and build
|
||||
./gradlew clean build
|
||||
|
||||
# Git stuff
|
||||
git add .
|
||||
git commit -m "${MESSAGE}"
|
||||
git tag ${VERSION}
|
||||
git push origin master
|
||||
git push --tags
|
||||
|
||||
echo "UsbSerial: Release Finished!!!"
|
|
@ -1 +1 @@
|
|||
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports'
|
||||
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports', ':integrationapp'
|
|
@ -19,6 +19,7 @@ android {
|
|||
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
|
||||
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
|
||||
archivesBaseName = "${project.name}-${project.VERSION_NAME}"
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
|
|
|
@ -15,3 +15,6 @@
|
|||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.*
|
|
@ -144,7 +144,8 @@ public class CP210xIds
|
|||
createDevice(0x3195, 0xF190),
|
||||
createDevice(0x3195, 0xF280),
|
||||
createDevice(0x3195, 0xF281),
|
||||
createDevice(0x413C, 0x9500)
|
||||
createDevice(0x413C, 0x9500),
|
||||
createDevice(0x1908, 0x2311) //serial of CMOS camera
|
||||
);
|
||||
|
||||
public static boolean isDeviceSupported(int vendorId, int productId)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.felhr.deviceids;
|
||||
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
|
||||
import static com.felhr.deviceids.Helpers.createTable;
|
||||
import static com.felhr.deviceids.Helpers.createDevice;
|
||||
|
||||
|
@ -251,7 +254,6 @@ public class FTDISioIds
|
|||
createDevice(0x03eb, 0x2109),
|
||||
createDevice(0x0456, 0xf000),
|
||||
createDevice(0x0456, 0xf001),
|
||||
createDevice(0x04d8, 0x000a),
|
||||
createDevice(0x0584, 0xb020),
|
||||
createDevice(0x0647, 0x0100),
|
||||
createDevice(0x06CE, 0x8311),
|
||||
|
@ -560,7 +562,25 @@ public class FTDISioIds
|
|||
createDevice(0x0403, 0x0) //fake FTDI reprogrammed by driver
|
||||
);
|
||||
|
||||
public static boolean isDeviceSupported(int vendorId, int productId) {
|
||||
private static boolean isMicrochipFtdi(UsbDevice dev) {
|
||||
if (dev.getVendorId() != 0x04d8 || dev.getProductId() != 0x000a)
|
||||
return false;
|
||||
for (int i = 0; i < dev.getInterfaceCount(); i++) {
|
||||
UsbInterface intf = dev.getInterface(i);
|
||||
if (intf.getInterfaceClass() == 0xff && intf.getInterfaceSubclass() == 0xff &&
|
||||
intf.getInterfaceProtocol() == 0x00)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isDeviceSupported(UsbDevice dev) {
|
||||
return Helpers.exists(ftdiDevices, dev.getVendorId(), dev.getProductId()) ||
|
||||
isMicrochipFtdi(dev);
|
||||
|
||||
}
|
||||
|
||||
static boolean isDeviceIdSupported(int vendorId, int productId) {
|
||||
return Helpers.exists(ftdiDevices, vendorId, productId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,21 @@ package com.felhr.usbserial;
|
|||
abstract class AbstractWorkerThread extends Thread {
|
||||
boolean firstTime = true;
|
||||
private volatile boolean keep = true;
|
||||
private volatile Thread workingThread;
|
||||
|
||||
void stopThread() {
|
||||
keep = false;
|
||||
if (this.workingThread != null) {
|
||||
this.workingThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public final void run() {
|
||||
while (keep) {
|
||||
if (!this.keep) {
|
||||
return;
|
||||
}
|
||||
this.workingThread = Thread.currentThread();
|
||||
while (this.keep && (!this.workingThread.isInterrupted())) {
|
||||
doRun();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -203,6 +203,12 @@ public class BLED112SerialDevice extends UsbSerialDevice
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
private final UsbInterface mInterface;
|
||||
private UsbEndpoint inEndpoint;
|
||||
private UsbEndpoint outEndpoint;
|
||||
private int cdcControl = 0;
|
||||
|
||||
private int initialBaudRate = 0;
|
||||
|
||||
|
@ -62,6 +63,7 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
public CDCSerialDevice(UsbDevice device, UsbDeviceConnection connection, int iface)
|
||||
{
|
||||
super(device, connection);
|
||||
cdcControl = findFirstControl(device); // Not sure how to find the control interface for others.
|
||||
mInterface = device.getInterface(iface >= 0 ? iface : findFirstCDC(device));
|
||||
}
|
||||
|
||||
|
@ -245,6 +247,12 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
@ -337,7 +345,7 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
|
||||
// Default Setup
|
||||
setControlCommand(CDC_SET_LINE_CODING, 0, getInitialLineCoding());
|
||||
setControlCommand(CDC_SET_CONTROL_LINE_STATE, CDC_CONTROL_LINE_OFF, null);
|
||||
setControlCommand(CDC_SET_CONTROL_LINE_STATE, CDC_CONTROL_LINE_ON, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -366,7 +374,7 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
{
|
||||
dataLength = data.length;
|
||||
}
|
||||
int response = connection.controlTransfer(CDC_REQTYPE_HOST2DEVICE, request, value, 0, data, dataLength, USB_TIMEOUT);
|
||||
int response = connection.controlTransfer(CDC_REQTYPE_HOST2DEVICE, request, value, cdcControl, data, dataLength, USB_TIMEOUT);
|
||||
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
|
||||
return response;
|
||||
}
|
||||
|
@ -374,7 +382,7 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
private byte[] getLineCoding()
|
||||
{
|
||||
byte[] data = new byte[7];
|
||||
int response = connection.controlTransfer(CDC_REQTYPE_DEVICE2HOST, CDC_GET_LINE_CODING, 0, 0, data, data.length, USB_TIMEOUT);
|
||||
int response = connection.controlTransfer(CDC_REQTYPE_DEVICE2HOST, CDC_GET_LINE_CODING, 0, cdcControl, data, data.length, USB_TIMEOUT);
|
||||
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
|
||||
return data;
|
||||
}
|
||||
|
@ -395,4 +403,21 @@ public class CDCSerialDevice extends UsbSerialDevice
|
|||
return -1;
|
||||
}
|
||||
|
||||
private static int findFirstControl(UsbDevice device)
|
||||
{
|
||||
int interfaceCount = device.getInterfaceCount();
|
||||
|
||||
for (int iIndex = 0; iIndex < interfaceCount; ++iIndex)
|
||||
{
|
||||
if (device.getInterface(iIndex).getInterfaceClass() == UsbConstants.USB_CLASS_COMM)
|
||||
{
|
||||
Log.i(CLASS_ID, "Using CDC control interface " + String.valueOf(iIndex));
|
||||
return iIndex;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(CLASS_ID, "There is no CDC control interface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,6 +66,12 @@ public class CH34xSerialDevice extends UsbSerialDevice
|
|||
|
||||
private static final int CH34X_921600_1312 = 0xf387;
|
||||
|
||||
private static final int CH34X_1228800_1312 = 0xfb03;
|
||||
private static final int CH34X_1228800_0f2c = 0x21;
|
||||
|
||||
private static final int CH34X_2000000_1312 = 0xfd03;
|
||||
private static final int CH34X_2000000_0f2c = 0x02;
|
||||
|
||||
// Parity values
|
||||
private static final int CH34X_PARITY_NONE = 0xc3;
|
||||
private static final int CH34X_PARITY_ODD = 0xcb;
|
||||
|
@ -250,6 +256,16 @@ public class CH34xSerialDevice extends UsbSerialDevice
|
|||
int ret = setBaudRate(CH34X_921600_1312, CH34X_19200_0f2c_rest);
|
||||
if(ret == -1)
|
||||
Log.i(CLASS_ID, "SetBaudRate failed!");
|
||||
} else if(baudRate > 921600 && baudRate <= 1228800)
|
||||
{
|
||||
int ret = setBaudRate(CH34X_1228800_1312, CH34X_1228800_0f2c);
|
||||
if(ret == -1)
|
||||
Log.i(CLASS_ID, "SetBaudRate failed!");
|
||||
} else if(baudRate > 1228800 && baudRate <= 2000000)
|
||||
{
|
||||
int ret = setBaudRate(CH34X_2000000_1312, CH34X_2000000_0f2c);
|
||||
if(ret == -1)
|
||||
Log.i(CLASS_ID, "SetBaudRate failed!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,6 +283,12 @@ public class CH34xSerialDevice extends UsbSerialDevice
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
//TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParity(int parity)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ public class CP2102SerialDevice extends UsbSerialDevice
|
|||
private static final int CP210x_SET_BAUDDIV = 0x01;
|
||||
private static final int CP210x_SET_LINE_CTL = 0x03;
|
||||
private static final int CP210x_GET_LINE_CTL = 0x04;
|
||||
private static final int CP210X_SET_BREAK = 0x05;
|
||||
private static final int CP210x_SET_MHS = 0x07;
|
||||
private static final int CP210x_SET_BAUDRATE = 0x1E;
|
||||
private static final int CP210x_SET_FLOW = 0x13;
|
||||
|
@ -31,6 +32,9 @@ public class CP2102SerialDevice extends UsbSerialDevice
|
|||
private static final int CP210x_REQTYPE_HOST2DEVICE = 0x41;
|
||||
private static final int CP210x_REQTYPE_DEVICE2HOST = 0xC1;
|
||||
|
||||
private static final int CP210x_BREAK_ON = 0x0001;
|
||||
private static final int CP210x_BREAK_OFF = 0x0000;
|
||||
|
||||
private static final int CP210x_MHS_RTS_ON = 0x202;
|
||||
private static final int CP210x_MHS_RTS_OFF = 0x200;
|
||||
private static final int CP210x_MHS_DTR_ON = 0x101;
|
||||
|
@ -326,6 +330,16 @@ public class CP2102SerialDevice extends UsbSerialDevice
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
if (state) {
|
||||
setControlCommand(CP210X_SET_BREAK, CP210x_BREAK_ON, null);
|
||||
} else {
|
||||
setControlCommand(CP210X_SET_BREAK, CP210x_BREAK_OFF, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
|
|
@ -2,12 +2,14 @@ package com.felhr.usbserial;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.hardware.usb.UsbRequest;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import com.felhr.utils.SafeUsbRequest;
|
||||
|
@ -35,6 +37,13 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
private static final int FTDI_SIO_SET_RTS_HIGH = (2 | (FTDI_SIO_SET_RTS_MASK << 8));
|
||||
private static final int FTDI_SIO_SET_RTS_LOW = (0 | (FTDI_SIO_SET_RTS_MASK << 8));
|
||||
|
||||
/**
|
||||
* BREAK on/off values obtained from linux driver
|
||||
* https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ftdi_sio.h
|
||||
*/
|
||||
private static final int FTDI_SIO_SET_BREAK_ON = (1<<14);
|
||||
private static final int FTDI_SIO_SET_BREAK_OFF = (0<<14);
|
||||
|
||||
public static final int FTDI_BAUDRATE_300 = 0x2710;
|
||||
public static final int FTDI_BAUDRATE_600 = 0x1388;
|
||||
public static final int FTDI_BAUDRATE_1200 = 0x09c4;
|
||||
|
@ -91,7 +100,6 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
private UsbSerialInterface.UsbOverrunCallback overrunCallback;
|
||||
private UsbSerialInterface.UsbBreakCallback breakCallback;
|
||||
|
||||
|
||||
public FTDISerialDevice(UsbDevice device, UsbDeviceConnection connection)
|
||||
{
|
||||
this(device, connection, -1);
|
||||
|
@ -186,38 +194,13 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
@Override
|
||||
public void setBaudRate(int baudRate)
|
||||
{
|
||||
int value = 0;
|
||||
if(baudRate >= 0 && baudRate <= 300 )
|
||||
value = FTDI_BAUDRATE_300;
|
||||
else if(baudRate > 300 && baudRate <= 600)
|
||||
value = FTDI_BAUDRATE_600;
|
||||
else if(baudRate > 600 && baudRate <= 1200)
|
||||
value = FTDI_BAUDRATE_1200;
|
||||
else if(baudRate > 1200 && baudRate <= 2400)
|
||||
value = FTDI_BAUDRATE_2400;
|
||||
else if(baudRate > 2400 && baudRate <= 4800)
|
||||
value = FTDI_BAUDRATE_4800;
|
||||
else if(baudRate > 4800 && baudRate <= 9600)
|
||||
value = FTDI_BAUDRATE_9600;
|
||||
else if(baudRate > 9600 && baudRate <=19200)
|
||||
value = FTDI_BAUDRATE_19200;
|
||||
else if(baudRate > 19200 && baudRate <= 38400)
|
||||
value = FTDI_BAUDRATE_38400;
|
||||
else if(baudRate > 19200 && baudRate <= 57600)
|
||||
value = FTDI_BAUDRATE_57600;
|
||||
else if(baudRate > 57600 && baudRate <= 115200)
|
||||
value = FTDI_BAUDRATE_115200;
|
||||
else if(baudRate > 115200 && baudRate <= 230400)
|
||||
value = FTDI_BAUDRATE_230400;
|
||||
else if(baudRate > 230400 && baudRate <= 460800)
|
||||
value = FTDI_BAUDRATE_460800;
|
||||
else if(baudRate > 460800 && baudRate <= 921600)
|
||||
value = FTDI_BAUDRATE_921600;
|
||||
else if(baudRate > 921600)
|
||||
value = FTDI_BAUDRATE_921600;
|
||||
else
|
||||
value = FTDI_BAUDRATE_9600;
|
||||
setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0);
|
||||
short[] encodedBaudRate = encodedBaudRate(baudRate);
|
||||
|
||||
if(encodedBaudRate != null) {
|
||||
setEncodedBaudRate(encodedBaudRate);
|
||||
}else{
|
||||
setOldBaudRate(baudRate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -374,6 +357,21 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BREAK on/off methods obtained from linux driver
|
||||
* https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ftdi_sio.c
|
||||
*/
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
if(state){
|
||||
currentSioSetData |= FTDI_SIO_SET_BREAK_ON;
|
||||
}else{
|
||||
currentSioSetData &= ~(FTDI_SIO_SET_BREAK_ON);
|
||||
}
|
||||
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
@ -539,6 +537,30 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
|
||||
public class FTDIUtilities
|
||||
{
|
||||
// Special treatment needed to FTDI devices
|
||||
public byte[] adaptArray(byte[] ftdiData)
|
||||
{
|
||||
int length = ftdiData.length;
|
||||
if(length > 64)
|
||||
{
|
||||
int n = 1;
|
||||
int p = 64;
|
||||
// Precalculate length without FTDI headers
|
||||
while(p < length)
|
||||
{
|
||||
n++;
|
||||
p = n*64;
|
||||
}
|
||||
int realLength = length - n*2;
|
||||
byte[] data = new byte[realLength];
|
||||
copyData(ftdiData, data);
|
||||
return data;
|
||||
}else
|
||||
{
|
||||
return Arrays.copyOfRange(ftdiData, 2, length);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkModemStatus(byte[] data)
|
||||
{
|
||||
if(data.length == 0) // Safeguard for zero length arrays
|
||||
|
@ -652,7 +674,7 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
|
||||
if(numberBytes > 2) // Data received
|
||||
{
|
||||
byte[] newBuffer = adaptArray(tempBuffer);
|
||||
byte[] newBuffer = this.ftdiUtilities.adaptArray(tempBuffer);
|
||||
System.arraycopy(newBuffer, 0, buffer, 0, buffer.length);
|
||||
|
||||
int p = numberBytes / 64;
|
||||
|
@ -666,4 +688,246 @@ public class FTDISerialDevice extends UsbSerialDevice
|
|||
|
||||
return readen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int syncRead(byte[] buffer, int offset, int length, int timeout) {
|
||||
|
||||
long beginTime = System.currentTimeMillis();
|
||||
long stopTime = beginTime + timeout;
|
||||
|
||||
if(asyncMode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(buffer == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = length / 62;
|
||||
if(length % 62 != 0)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
|
||||
byte[] tempBuffer = new byte[length + n * 2];
|
||||
|
||||
int readen = 0;
|
||||
|
||||
do
|
||||
{
|
||||
int timeLeft = 0;
|
||||
if(timeout > 0)
|
||||
{
|
||||
timeLeft = (int) (stopTime - System.currentTimeMillis());
|
||||
if (timeLeft <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int numberBytes = connection.bulkTransfer(inEndpoint, tempBuffer, tempBuffer.length, timeLeft);
|
||||
|
||||
if(numberBytes > 2) // Data received
|
||||
{
|
||||
byte[] newBuffer = this.ftdiUtilities.adaptArray(tempBuffer);
|
||||
System.arraycopy(newBuffer, 0, buffer, offset, length);
|
||||
|
||||
int p = numberBytes / 64;
|
||||
if(numberBytes % 64 != 0)
|
||||
{
|
||||
p++;
|
||||
}
|
||||
readen = numberBytes - p * 2;
|
||||
}
|
||||
}while(readen <= 0);
|
||||
|
||||
return readen;
|
||||
}
|
||||
|
||||
private static final byte[] skip = new byte[2];
|
||||
|
||||
/**
|
||||
* This method avoids creation of garbage by reusing the same
|
||||
* array instance for skipping header bytes and running
|
||||
* {@link UsbDeviceConnection#bulkTransfer(UsbEndpoint, byte[], int, int, int)}
|
||||
* directly.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
private int readSyncJelly(byte[] buffer, int timeout, long stopTime) {
|
||||
int read = 0;
|
||||
do
|
||||
{
|
||||
int timeLeft = 0;
|
||||
if(timeout > 0)
|
||||
{
|
||||
timeLeft = (int) (stopTime - System.currentTimeMillis());
|
||||
if (timeLeft <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int numberBytes = connection.bulkTransfer(inEndpoint, skip, skip.length, timeLeft);
|
||||
|
||||
if(numberBytes > 2) // Data received
|
||||
{
|
||||
numberBytes = connection.bulkTransfer(inEndpoint, buffer, read, 62, timeLeft);
|
||||
read += numberBytes;
|
||||
}
|
||||
} while(read <= 0);
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/47303802/how-is-androids-string-usbdevice-getversion-encoded-from-word-bcddevice
|
||||
private short getBcdDevice() {
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
|
||||
byte[] descriptors = connection.getRawDescriptors();
|
||||
return (short) ((descriptors[13] << 8) + descriptors[12]);
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private byte getISerialNumber(){
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
|
||||
byte[] descriptors = connection.getRawDescriptors();
|
||||
return descriptors[16];
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBaudTolerated(long speed, long target) {
|
||||
return ((speed >= (target * 100) / 103) &&
|
||||
(speed <= (target * 100) / 97));
|
||||
}
|
||||
|
||||
// Encoding baudrate as freebsd driver:
|
||||
// https://github.com/freebsd/freebsd/blob/1d6e4247415d264485ee94b59fdbc12e0c566fd0/sys/dev/usb/serial/uftdi.c
|
||||
private short[] encodedBaudRate(int baudRate){
|
||||
boolean isFT232A = false;
|
||||
boolean clk12MHz = false;
|
||||
boolean hIndex = false;
|
||||
|
||||
short[] ret = new short[2];
|
||||
int clk, divisor, fastClk, frac, hwSpeed;
|
||||
|
||||
byte[] encodedFraction = new byte[]{
|
||||
0, 3, 2, 4, 1, 5, 6, 7
|
||||
};
|
||||
|
||||
byte[] roundoff232a = new byte[]{
|
||||
0, 1, 0, 1, 0, -1, 2, 1,
|
||||
0, -1, -2, -3, 4, 3, 2, 1,
|
||||
};
|
||||
|
||||
short bcdDevice = getBcdDevice();
|
||||
|
||||
if(bcdDevice == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(bcdDevice == 0x200 && getISerialNumber() == 0) {
|
||||
isFT232A = true;
|
||||
}
|
||||
|
||||
if(bcdDevice == 0x500 || bcdDevice == 0x700 || bcdDevice == 0x800 || bcdDevice == 0x900 || bcdDevice == 0x1000) {
|
||||
hIndex = true;
|
||||
}
|
||||
|
||||
if(bcdDevice == 0x700 || bcdDevice == 0x800 || bcdDevice == 0x900 ) {
|
||||
clk12MHz = true;
|
||||
}
|
||||
|
||||
if(baudRate >= 1200 && clk12MHz) {
|
||||
clk = 12000000;
|
||||
fastClk = (1 << 17);
|
||||
}else {
|
||||
clk = 3000000;
|
||||
fastClk = 0;
|
||||
}
|
||||
|
||||
if(baudRate < (clk >> 14) || baudRate > clk) {
|
||||
return null;
|
||||
}
|
||||
|
||||
divisor = (clk << 4) / baudRate;
|
||||
if((divisor & 0xf) == 1) {
|
||||
divisor &= 0xfffffff8;
|
||||
}else if (isFT232A) {
|
||||
divisor += roundoff232a[divisor & 0x0f];
|
||||
}else {
|
||||
divisor += 1; /* Rounds odd 16ths up to next 8th. */
|
||||
}
|
||||
divisor >>= 1;
|
||||
|
||||
hwSpeed = (clk << 3) / divisor;
|
||||
|
||||
if(!isBaudTolerated(hwSpeed, baudRate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
frac = divisor & 0x07;
|
||||
divisor >>= 3;
|
||||
if (divisor == 1) {
|
||||
if (frac == 0) {
|
||||
divisor = 0; /* 1.0 becomes 0.0 */
|
||||
}else {
|
||||
frac = 0; /* 1.5 becomes 1.0 */
|
||||
}
|
||||
}
|
||||
divisor |= (encodedFraction[frac] << 14) | fastClk;
|
||||
|
||||
ret[0] = (short) divisor; //loBits
|
||||
ret[1] = hIndex ?
|
||||
(short) ((divisor >> 8) & 0xFF00 | (mInterface.getId() + 1))
|
||||
: (short) (divisor >> 16); //hiBits
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void setEncodedBaudRate(short[] encodedBaudRate) {
|
||||
connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, FTDI_SIO_SET_BAUD_RATE
|
||||
, encodedBaudRate[0], encodedBaudRate[1], null, 0, USB_TIMEOUT);
|
||||
}
|
||||
|
||||
private void setOldBaudRate(int baudRate) {
|
||||
int value = 0;
|
||||
if(baudRate >= 0 && baudRate <= 300 )
|
||||
value = FTDI_BAUDRATE_300;
|
||||
else if(baudRate > 300 && baudRate <= 600)
|
||||
value = FTDI_BAUDRATE_600;
|
||||
else if(baudRate > 600 && baudRate <= 1200)
|
||||
value = FTDI_BAUDRATE_1200;
|
||||
else if(baudRate > 1200 && baudRate <= 2400)
|
||||
value = FTDI_BAUDRATE_2400;
|
||||
else if(baudRate > 2400 && baudRate <= 4800)
|
||||
value = FTDI_BAUDRATE_4800;
|
||||
else if(baudRate > 4800 && baudRate <= 9600)
|
||||
value = FTDI_BAUDRATE_9600;
|
||||
else if(baudRate > 9600 && baudRate <=19200)
|
||||
value = FTDI_BAUDRATE_19200;
|
||||
else if(baudRate > 19200 && baudRate <= 38400)
|
||||
value = FTDI_BAUDRATE_38400;
|
||||
else if(baudRate > 19200 && baudRate <= 57600)
|
||||
value = FTDI_BAUDRATE_57600;
|
||||
else if(baudRate > 57600 && baudRate <= 115200)
|
||||
value = FTDI_BAUDRATE_115200;
|
||||
else if(baudRate > 115200 && baudRate <= 230400)
|
||||
value = FTDI_BAUDRATE_230400;
|
||||
else if(baudRate > 230400 && baudRate <= 460800)
|
||||
value = FTDI_BAUDRATE_460800;
|
||||
else if(baudRate > 460800 && baudRate <= 921600)
|
||||
value = FTDI_BAUDRATE_921600;
|
||||
else if(baudRate > 921600)
|
||||
value = FTDI_BAUDRATE_921600;
|
||||
else
|
||||
value = FTDI_BAUDRATE_9600;
|
||||
|
||||
setControlCommand(FTDI_SIO_SET_BAUD_RATE, value, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,6 +264,12 @@ public class PL2303SerialDevice extends UsbSerialDevice
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
|
|
@ -118,6 +118,7 @@ public class SerialBuffer
|
|||
} catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
byte[] dst;
|
||||
|
|
|
@ -54,6 +54,28 @@ public class SerialInputStream extends InputStream
|
|||
return device.syncRead(b, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len)
|
||||
{
|
||||
if(off < 0 ){
|
||||
throw new IndexOutOfBoundsException("Offset must be >= 0");
|
||||
}
|
||||
|
||||
if(len < 0){
|
||||
throw new IndexOutOfBoundsException("Length must positive");
|
||||
}
|
||||
|
||||
if(len > b.length - off) {
|
||||
throw new IndexOutOfBoundsException("Length greater than b.length - off");
|
||||
}
|
||||
|
||||
if (off == 0 && len == b.length) {
|
||||
return read(b);
|
||||
}
|
||||
|
||||
return device.syncRead(b, off, len, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
if(bufferSize > 0)
|
||||
|
|
|
@ -25,6 +25,29 @@ public class SerialOutputStream extends OutputStream
|
|||
device.syncWrite(b, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len)
|
||||
{
|
||||
if(off < 0 ){
|
||||
throw new IndexOutOfBoundsException("Offset must be >= 0");
|
||||
}
|
||||
|
||||
if(len < 0){
|
||||
throw new IndexOutOfBoundsException("Length must positive");
|
||||
}
|
||||
|
||||
if(off + len > b.length) {
|
||||
throw new IndexOutOfBoundsException("off + length greater than buffer length");
|
||||
}
|
||||
|
||||
if (off == 0 && len == b.length) {
|
||||
write(b);
|
||||
return;
|
||||
}
|
||||
|
||||
device.syncWrite(b, off, len, timeout);
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.felhr.deviceids.CP210xIds;
|
|||
import com.felhr.deviceids.FTDISioIds;
|
||||
import com.felhr.deviceids.PL2303Ids;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
|
@ -22,7 +23,9 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
|
||||
protected static final String COM_PORT = "COM ";
|
||||
|
||||
private static final boolean mr1Version;
|
||||
// Android version < 4.3 It is not going to be asynchronous read operations
|
||||
static final boolean mr1Version =
|
||||
android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
|
||||
protected final UsbDevice device;
|
||||
protected final UsbDeviceConnection connection;
|
||||
|
||||
|
@ -47,15 +50,6 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
private String portName = "";
|
||||
protected boolean isOpen;
|
||||
|
||||
// Get Android version if version < 4.3 It is not going to be asynchronous read operations
|
||||
static
|
||||
{
|
||||
if(android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
mr1Version = true;
|
||||
else
|
||||
mr1Version = false;
|
||||
}
|
||||
|
||||
public UsbSerialDevice(UsbDevice device, UsbDeviceConnection connection)
|
||||
{
|
||||
this.device = device;
|
||||
|
@ -79,7 +73,7 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
int vid = device.getVendorId();
|
||||
int pid = device.getProductId();
|
||||
|
||||
if(FTDISioIds.isDeviceSupported(vid, pid))
|
||||
if(FTDISioIds.isDeviceSupported(device))
|
||||
return new FTDISerialDevice(device, connection, iface);
|
||||
else if(CP210xIds.isDeviceSupported(vid, pid))
|
||||
return new CP2102SerialDevice(device, connection, iface);
|
||||
|
@ -114,7 +108,7 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
int vid = device.getVendorId();
|
||||
int pid = device.getProductId();
|
||||
|
||||
if(FTDISioIds.isDeviceSupported(vid, pid))
|
||||
if(FTDISioIds.isDeviceSupported(device))
|
||||
return true;
|
||||
else if(CP210xIds.isDeviceSupported(vid, pid))
|
||||
return true;
|
||||
|
@ -223,6 +217,35 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
return connection.bulkTransfer(inEndpoint, buffer, buffer.length, timeout);
|
||||
}
|
||||
|
||||
@TargetApi(18)
|
||||
@Override
|
||||
public int syncWrite(byte[] buffer, int offset, int length, int timeout) {
|
||||
if(!asyncMode)
|
||||
{
|
||||
if(buffer == null)
|
||||
return 0;
|
||||
|
||||
return connection.bulkTransfer(outEndpoint, buffer, offset, length, timeout);
|
||||
}else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(18)
|
||||
@Override
|
||||
public int syncRead(byte[] buffer, int offset, int length, int timeout) {
|
||||
if(asyncMode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer == null)
|
||||
return 0;
|
||||
|
||||
return connection.bulkTransfer(inEndpoint, buffer, offset, length, timeout);
|
||||
}
|
||||
|
||||
// Serial port configuration
|
||||
@Override
|
||||
public abstract void setBaudRate(int baudRate);
|
||||
|
@ -234,6 +257,8 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
public abstract void setParity(int parity);
|
||||
@Override
|
||||
public abstract void setFlowControl(int flowControl);
|
||||
@Override
|
||||
public abstract void setBreak(boolean state);
|
||||
|
||||
public SerialInputStream getInputStream() {
|
||||
if(asyncMode)
|
||||
|
@ -455,14 +480,13 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
|
|||
|
||||
protected void setThreadsParams(UsbRequest request, UsbEndpoint endpoint)
|
||||
{
|
||||
writeThread.setUsbEndpoint(endpoint);
|
||||
if(mr1Version)
|
||||
{
|
||||
workerThread.setUsbRequest(request);
|
||||
writeThread.setUsbEndpoint(endpoint);
|
||||
}else
|
||||
{
|
||||
readThread.setUsbEndpoint(request.getEndpoint());
|
||||
writeThread.setUsbEndpoint(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ public interface UsbSerialInterface
|
|||
boolean syncOpen();
|
||||
int syncWrite(byte[] buffer, int timeout);
|
||||
int syncRead(byte[] buffer, int timeout);
|
||||
int syncWrite(byte[] buffer, int offset, int length, int timeout);
|
||||
int syncRead(byte[] buffer, int offset, int length, int timeout);
|
||||
void syncClose();
|
||||
|
||||
// Serial port configuration
|
||||
|
@ -46,6 +48,7 @@ public interface UsbSerialInterface
|
|||
void setStopBits(int stopBits);
|
||||
void setParity(int parity);
|
||||
void setFlowControl(int flowControl);
|
||||
void setBreak(boolean state);
|
||||
|
||||
// Flow control commands and interface callback
|
||||
void setRTS(boolean state);
|
||||
|
|
|
@ -297,6 +297,12 @@ public class XdcVcpSerialDevice extends UsbSerialDevice
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBreak(boolean state)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRTS(boolean state)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ public class DeviceIdTest {
|
|||
|
||||
for (TestCase tc : cases) {
|
||||
Assert.assertTrue(CP210xIds.isDeviceSupported(tc.vendor, tc.product));
|
||||
Assert.assertFalse(FTDISioIds.isDeviceSupported(tc.vendor, tc.product));
|
||||
Assert.assertFalse(FTDISioIds.isDeviceIdSupported(tc.vendor, tc.product));
|
||||
}
|
||||
}
|
||||
|
||||
|
|