Porównaj commity

...

76 Commity

Autor SHA1 Wiadomość Data
green-green-avk 7ad6c9f688
Merge pull request #334 from green-green-avk/build-env-update
Updating build settings to support current Android Studio and its JRE
2023-04-28 18:35:06 -07:00
green-green-avk 9b915b2f84
release.sh a+x 2021-06-14 20:31:38 -07:00
green-green-avk 7fe4ce6e50
jcenter() expired: => mavenCentral() 2021-06-14 20:31:38 -07:00
alex 94838280cd
Gradle 6.7.1 / AGP 4.2.1 2021-06-14 20:31:33 -07:00
green-green-avk 7fff8b6d5c
Update RELEASING.md 2021-06-14 20:23:58 -07:00
green-green-avk 4353bf1f4f
Merge pull request #333 from green-green-avk/fix-ftdi-baudrate-multiport
FTDI: Fix baudrate setting on multiport devices
2021-06-14 19:18:10 -07:00
alex f0dda6635c
FTDI: Fix baudrate setting on multiport devices
Correction of https://github.com/felHR85/UsbSerial/pull/274
2021-06-14 18:44:59 -07:00
green-green-avk f537d13ede
Merge pull request #270 from changwoo/ftdi-fix-usb-desc-endian
ftdi: Fix bcdDevice endian
2021-06-14 10:20:15 -07:00
green-green-avk 3e0fe32f16
Merge pull request #314 from mobilinkd/CDC-Control
Use proper control index on multi-class CDC devices
2021-06-14 10:18:21 -07:00
Rob Riggs 6987b48e14 Find the proper control index to use for CDC devices with multiple devices classes present. This fixes the problem which prevented the library from working with STM32 Nucleo boards, among others. 2020-06-12 21:30:12 -05:00
Felipe Herranz 319cb9de68
Looking for collaborators 2020-06-12 18:11:16 +02:00
Changwoo Ryu 37eac8d477 ftdi: Fix bcdDevice endian 2019-08-02 20:14:42 +09:00
Felipe Herranz 828809f874 changelog 2019-07-11 23:39:59 +02:00
Felipe Herranz 08ef5bbb3f release 6.1.0 2019-07-11 23:31:57 +02:00
Felipe Herranz 85c69b540d
Merge pull request #261 from winy57/contribution
Added setBreak method for CP21012 devices
2019-07-11 22:28:20 +02:00
Felipe Herranz b967da3c54
Merge pull request #262 from felHR85/rabidaudio-outputstream-fix
Added sync and streams read/write methods with offsets
2019-07-11 22:20:35 +02:00
Mickael Storck f4889f03cb Added setBreak method for CP21012 devices 2019-07-11 11:03:42 +02:00
Felipe Herranz d0232ed59a
Merge pull request #255 from TheSven73/fix-microchip-v2
Correctly determine Microchip pid:vid 04d8:000a device class
2019-07-07 23:46:12 +02:00
Felipe Herranz 538e2e0483 using syncWrite and syncRead new methods in Streams 2019-07-07 23:07:42 +02:00
Felipe Herranz 90396ab436 ftdi adapted for syncRead with offset method 2019-07-07 22:36:22 +02:00
Felipe Herranz fdfb9f1053 added syncRead with offset except in FTDI 2019-07-07 15:41:19 +02:00
Felipe Herranz 1e68f744c5 checking corner cases 2019-07-07 13:09:12 +02:00
Felipe Herranz 58bc4a47c3
Merge pull request #256 from felHR85/ftdi_sync_fix
Back to previous FTDI sync read method. Referenced in #241
2019-07-06 20:48:41 +02:00
Felipe Herranz f0898c3c1d
Merge pull request #245 from janimm/CH34X_baud_rates
Added baud rates 1228800 and 2000000 to CH34X driver
2019-07-06 20:44:05 +02:00
Felipe Herranz 2f4a4de99c changed sync tests 2019-07-05 22:44:45 +02:00
Felipe Herranz 10d1088228 updated with master 2019-07-04 22:49:17 +02:00
Felipe Herranz 4e74b05689
Merge pull request #257 from felHR85/integration_api_tests
Added sync mode in integration app
2019-07-04 22:30:18 +02:00
Felipe Herranz e9eb771541 added sync mode in integration app 2019-07-04 21:46:33 +02:00
Felipe Herranz 9f32a3b7e9 back to previous ftdi syncRead method 2019-07-03 23:36:44 +02:00
Sven Van Asbroeck 6180eb497c Correctly determine Microchip pid:vid 04d8:000a device class
According to the Linux kernel tree [1], Microchip pid:vid 04d8:000a
is generally a CDC ACM device, implemented by a demo firmware
application.

However, some vendors have re-used this vid:pid for other types of
firmware, emulating FTDI chips. The Linux kernel attempts to detect
such cases by matching on interface class/subclass/proto. If these
are ff/ff/00 it uses FTDI, otherwise CDC.

Mimic the Linux kernel's logic in determining whether the Microchip
device is CDC or FTDI.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f08dea734844aa42ec57c229b0b73b3d7d21f810
2019-07-02 10:17:12 -04:00
Charles Julian Knight f52c67a134 added chunked stream methods 2019-06-26 13:39:01 -04:00
Felipe Herranz 91a5368445
Update README.md 2019-05-27 21:57:48 +02:00
Felipe Herranz ffe964f672
fixed link 2019-05-27 01:20:11 +02:00
Felipe Herranz 8261ea855c
Added videotutorials in the wiki 2019-05-27 01:19:18 +02:00
jani c0c5a2848c Added baud rates 1228800 and 2000000 to CH34X driver 2019-05-03 13:45:41 +03:00
Felipe Herranz 3465c5041e changelog updated 2019-05-01 21:21:06 +02:00
Felipe Herranz 1823f2b167 release 6.0.6 2019-05-01 20:59:58 +02:00
Felipe Herranz 1e672fcb96
Merge pull request #243 from felHR85/ftdi_custom_baudrates
Ftdi custom baudrates
2019-05-01 19:47:00 +02:00
Felipe Herranz bef34df377
Merge pull request #240 from xtoolbox/feature_set_break
Add a setBreak interface to support the set break feature
2019-05-01 19:25:26 +02:00
xiongyi 33fed5e09c add a setBreak interface to set the break feature, now tested on FTDI chip. 2019-04-26 10:03:48 +08:00
Felipe Herranz b6aef50017
Readme updated with debugging info 2019-04-07 22:03:33 +02:00
Felipe Herranz 217d651f68 correction in changelog 2019-04-06 12:51:46 +02:00
Felipe Herranz f07bb50b28 updated changelog 2019-04-06 01:15:07 +02:00
Felipe Herranz ca5379f9c4 release 6.0.5 2019-04-06 01:04:00 +02:00
Felipe Herranz 5eddda99e9
Merge pull request #228 from t2t-sonbui/fix-write-thread
Fix Write Thread does not stop when close port
2019-04-06 00:39:47 +02:00
Felipe Herranz 41ced7c2a7
Merge pull request #229 from felHR85/cdc_fix
CDC Default Setup to CDC_CONTROL_LINE_ON
2019-04-06 00:03:02 +02:00
Felipe Herranz 2afa82ddc3
Merge pull request #225 from phuongnam0907/patch-1
Update CP210xIds.java
2019-04-06 00:02:37 +02:00
Felipe Herranz 8a0d9c8850 setBaudRated refactored 2019-04-05 23:40:08 +02:00
Felipe Herranz 9c51f4c19b cdc fix 2019-04-01 23:35:57 +02:00
Felipe Herranz 4108a6905e first version with custom baudrates 2019-03-31 22:10:21 +02:00
Felipe Herranz ac88abca1a added encoded baudrates in ftdi driver 2019-03-31 21:57:15 +02:00
sonbuidev 001e745a4a Fix Write Thread does not stop when close pory 2019-03-29 14:02:11 +07:00
phuongnam0907 5ec307966a
Update CP210xIds.java 2019-03-28 10:16:39 +07:00
Felipe Herranz 3e889f646f changelog 2019-03-09 21:55:15 +01:00
Felipe Herranz 9458b7f136 release 6.0.4 2019-03-09 21:46:15 +01:00
Felipe Herranz dcc5063197 release script modified 2019-03-09 21:27:34 +01:00
Felipe Herranz 566c20f2b3 changes 2019-03-09 21:15:31 +01:00
Felipe Herranz aad56b768b added colors in integration.py 2019-03-09 21:13:42 +01:00
Felipe Herranz da875752b1
Merge pull request #218 from Arneball/jellybeanapi
Reduce garbage by reading usb data right into the buffer on api >= jellybean
2019-03-09 20:55:26 +01:00
Felipe Herranz 1d7d0d9625
Deleted unused import 2019-03-09 02:05:12 +01:00
Felipe Herranz 324ec77db6
Merge pull request #216 from Arneball/proguard
Added proguard rules to the AAR-package
2019-03-09 01:54:22 +01:00
Felipe Herranz 1e4bd132cc
Merge pull request #219 from felHR85/release
Release script
2019-03-09 01:52:32 +01:00
Felipe Herranz 2487b609c5 version of release script 2019-03-09 01:44:41 +01:00
Raul Bache b5f7699a52 Runka 2019-03-04 14:26:35 +01:00
Felipe Herranz d369c0d31d added send_packet script 2019-03-03 22:04:15 +01:00
Felipe Herranz b5dd43e5d2 started release script 2019-03-03 22:01:28 +01:00
Felipe Herranz 47f606396c
Merge pull request #217 from felHR85/integration_tests
Integration tests
2019-03-03 18:16:56 +01:00
Felipe Herranz bd350b618e release of integration tests 2019-03-03 18:01:46 +01:00
Felipe Herranz 121598728b added integration script 2019-03-02 21:45:03 +01:00
Felipe Herranz 203a65eb54 first version of integration app 2019-03-02 18:42:24 +01:00
Raul Bache b98ea3278d Added proguard rules to the AAR-package 2019-02-26 11:04:13 +01:00
Felipe Herranz f30817c30f started integration test app 2019-02-24 19:29:01 +01:00
Felipe Herranz ed8cf6208e fix 2019-02-23 23:49:26 +01:00
Felipe Herranz d9b790f611 added firtst test 2019-02-23 23:45:56 +01:00
Felipe Herranz 7ae5df917f updating gitignore for python 2019-02-23 22:29:05 +01:00
Felipe Herranz 901590bd2e correction in CHANGELOG 2019-02-23 19:16:34 +01:00
60 zmienionych plików z 2057 dodań i 67 usunięć

6
.gitignore vendored
Wyświetl plik

@ -28,3 +28,9 @@ local.properties
# Gradle
build/
.gradle
# Byte-compiled / optimized / DLL files
__pycache__/
*.pyc
*.py[cod]
*$py.class

Wyświetl plik

@ -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.

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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()
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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(""))

Wyświetl plik

@ -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(""))

Wyświetl plik

@ -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))

Wyświetl plik

@ -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]*

Wyświetl plik

@ -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")

1
integrationapp/.gitignore vendored 100644
Wyświetl plik

@ -0,0 +1 @@
/build

Wyświetl plik

@ -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')
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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());
}
}

Wyświetl plik

@ -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>

Wyświetl plik

@ -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;
}
}
}
}

Wyświetl plik

@ -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);
}
}
}
}

Wyświetl plik

@ -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();
}
}
}
}
}
}

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Wyświetl plik

@ -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>

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.9 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.8 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.0 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.7 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.4 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 6.7 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 6.2 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 10 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 8.9 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Wyświetl plik

@ -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>

Wyświetl plik

@ -0,0 +1,3 @@
<resources>
<string name="app_name">IntegrationApp</string>
</resources>

Wyświetl plik

@ -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>

Wyświetl plik

@ -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);
}
}

54
release.sh 100755
Wyświetl plik

@ -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!!!"

Wyświetl plik

@ -1 +1 @@
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports'
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports', ':integrationapp'

Wyświetl plik

@ -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

Wyświetl plik

@ -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.*

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -203,6 +203,12 @@ public class BLED112SerialDevice extends UsbSerialDevice
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -264,6 +264,12 @@ public class PL2303SerialDevice extends UsbSerialDevice
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -118,6 +118,7 @@ public class SerialBuffer
} catch (InterruptedException e)
{
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
byte[] dst;

Wyświetl plik

@ -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)

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -297,6 +297,12 @@ public class XdcVcpSerialDevice extends UsbSerialDevice
}
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -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));
}
}