Porównaj commity

...

132 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
Felipe Herranz 1e6b5d3938 release 6.0.3 2019-02-23 19:14:53 +01:00
Felipe Herranz 050ffb8730 RELEASING.md updated 2019-02-23 19:07:20 +01:00
Felipe Herranz 234c83dd28
Merge pull request #212 from Arneball/reuseempty
Reuse same instance of byte array when the destination array is empty
2019-02-23 19:00:16 +01:00
Felipe Herranz 62502d5f1a
Merge pull request #210 from Arneball/allocation
Removed unneccesary classes and made a memory and cpu optimization
2019-02-23 13:46:47 +01:00
Felipe Herranz af18d10953
Removed unused import 2019-02-23 13:21:38 +01:00
Raul Bache b0f2fd2543 Removed "always-null" parameter 2019-02-20 10:04:23 +01:00
Arneball aeb1227fa2 Reuse same instance of byte array when the destination array is empty
Also using System.arrayCopy in loop instead of manual copying
2019-02-19 14:16:44 +01:00
Raul Bache d874292505 Removed unneccesary classes and made a memory and cpu optimization
After this commit, vendor-product-tuples are stored as longs internally.
This way heap size is conserved and specialized classes are omitted.

This might not be a big deal desktop applications, but for Android,
every bit counts.

The public api is unchanged

Added test to verify that things did not break
2019-02-18 14:52:06 +01:00
Felipe Herranz 37e5dfccd7 release 6.0.2 2019-02-17 18:11:07 +01:00
Felipe Herranz 0593683585
Merge pull request #205 from felHR85/multiple_ports_fix
Disconnect different UsbSerialDevice objects from same device
2019-02-17 18:01:15 +01:00
Felipe Herranz aec9b117bc
Update README.md 2019-02-07 00:31:57 +01:00
Felipe Herranz 1751188bd2
Update README.md 2019-02-07 00:31:38 +01:00
Felipe Herranz 04db5825c0 solving issue disconnecting one device with multiple serial ports 2019-01-30 23:47:16 +01:00
Felipe Herranz dc94ea5879 always recognize other people help 2019-01-27 19:22:56 +01:00
Felipe Herranz 9d801e780b added changelog 2019-01-27 19:16:06 +01:00
Felipe Herranz 3bce693b8d release 6.0.1 2019-01-27 18:44:28 +01:00
Felipe Herranz b5863e22cb changed protocol buffer 2019-01-27 18:31:30 +01:00
Felipe Herranz d02adc6b08
Merge pull request #201 from pawitp/patch-1
cp210x: Add support for "Windows Update" PIDs
2019-01-27 17:47:05 +01:00
Pawit Pornkitprasan f25cc0ab7b
cp210x: Add support for "Windows Update" PID
There are certain PID CP210x devices can be set to to allow Windows to
automatically download drivers from Windows Update. This patch adds
support for those PIDs.

Reference: https://www.silabs.com/community/interface/knowledge-base.entry.html/2016/12/30/downloading_cp210xd-ek07
2019-01-23 19:29:38 +07:00
Felipe Herranz ab242bd7b3 merge 2019-01-19 20:55:04 +01:00
Felipe Herranz bb69f4090a release 6.0.0 2019-01-19 20:51:52 +01:00
Felipe Herranz 7db4e625d3
Merge pull request #198 from felHR85/cdc_changes
Line off when starting CDC driver
2019-01-19 20:07:45 +01:00
Felipe Herranz 1030409eb2
Merge pull request #199 from felHR85/cp2102_bug
Fixes for databits, parity and stopbits in CP2102
2019-01-19 19:58:14 +01:00
Felipe Herranz 3c839efd2c
Merge pull request #196 from felHR85/cp2012_improvs
Purging CP2102 when closing
2019-01-19 19:44:28 +01:00
Felipe Herranz 8ee110590d buffer variables to final 2019-01-19 18:21:59 +01:00
Felipe Herranz fbf3b89b9d
Merge pull request #197 from felHR85/okio
Okio buffer and ProtocolBuffering
2019-01-19 18:07:47 +01:00
Felipe Herranz 3ad63c9311
Merge branch 'master' into okio 2019-01-19 17:30:42 +01:00
Felipe Herranz d43e1a2edb deleted comment 2019-01-19 17:27:58 +01:00
Felipe Herranz 6bdbbcb7d8
Merge pull request #195 from Arneball/master
Refactored so that all common thread methods are handled in a base class
2019-01-19 17:27:07 +01:00
Raul Bache f4a4bd95d0 Refactored so that all common thread methods are handled in a base class
After this commit, common functionality for threads are gathered in a base class.
Less code, removed AtomicBoolean since it can be replaced with a volatile boolean, eliminating an allocation

Some members are made final
2019-01-15 19:53:02 +01:00
Felipe Herranz e41b04b906 line off when starting CDC driver 2019-01-12 19:35:25 +01:00
Felipe Herranz e80893539a purging when closing 2019-01-12 13:35:03 +01:00
Felipe Herranz 9dfa8f6867
Merge pull request #194 from felHR85/example_close
closing port when service is destroyed
2019-01-12 12:19:24 +01:00
Felipe Herranz d280e05043 closing port when service is destroyed 2019-01-12 11:50:43 +01:00
Felipe Herranz 8f00b97d1a
Merge pull request #193 from mws-rmain/master
Ensure findSerialPortDevice() requests access ONLY to a supported device
2019-01-11 22:29:34 +01:00
Felipe Herranz e99d6b8d56 fixes for databits, parity and stopbits 2019-01-11 20:04:57 +01:00
mws-rmain 02201fef82
Fix Build Issues
Add missing import & TAG
2019-01-10 14:00:29 -05:00
mws-rmain dce98bb5ea
Fix Build Issues
Add missing import & TAG
2019-01-10 13:59:18 -05:00
mws-rmain e7439e3551
Fix build issues
Add missing import & TAG
2019-01-10 13:58:01 -05:00
mws-rmain e0af794877
Ensure findSerialPortDevice() requests access ONLY to a supported device
The hashmap returned by usbManager.getDeviceList() contains devices in random order. Access will be requested for the first supported device.
2019-01-09 11:38:56 -05:00
mws-rmain b5b9a16499
Ensure findSerialPortDevice() requests access ONLY to a supported device
The hashmap returned by usbManager.getDeviceList() contains devices in random order. Access will be requested for the first supported device.
2019-01-09 11:33:48 -05:00
mws-rmain aa4a19cd46
Ensure findSerialPortDevice() requests access ONLY to a supported device
The hashmap returned by usbManager.getDeviceList() contains devices in random order. Access will be requested for the first supported device.
2019-01-09 11:25:21 -05:00
Felipe Herranz 77ab67deca
Merge pull request #189 from mws-rmain/master
Add missing unregisterReceiver(usbReceiver) call
2019-01-06 20:46:47 +01:00
Felipe Herranz ff9f314406 avoiding 16kb limit in bulktransfers 2019-01-06 20:44:45 +01:00
Felipe Herranz 9a30dfb93b improved write async tests 2019-01-05 19:13:15 +01:00
Felipe Herranz a244d1a36f added tests for Read Buffer 2019-01-05 17:38:01 +01:00
Felipe Herranz 72d736bb46 merged with protocols buffer and testing write buffer with okio 2019-01-05 17:14:20 +01:00
Felipe Herranz 538a0d2a38 added okio buffer for write thread 2019-01-04 21:54:35 +01:00
mws-rmain d5da84072b
added unregisterReceiver(usbReceiver) to onDestroy() 2019-01-04 13:32:41 -05:00
mws-rmain 5d619c2e3c
added unregisterReceiver(usbReceiver) to onDestroy() 2019-01-04 13:31:49 -05:00
mws-rmain 4141c23813
added unregisterReceiver(usbReceiver) to onDestroy() 2019-01-04 13:30:24 -05:00
Felipe Herranz b2222b0c27 added unit tests for binary mode 2018-12-31 03:14:16 +01:00
Felipe Herranz d837762591 testing test mode 2018-12-30 03:07:24 +01:00
Felipe Herranz baa2db7c17 adding protocolbuffer test 2018-12-28 17:59:48 +01:00
Felipe Herranz 4a8e09dbf4 added regex 2018-12-27 21:01:44 +01:00
Felipe Herranz 491bf0c029 adding protocols buffer 2018-12-26 20:27:05 +01:00
75 zmienionych plików z 3967 dodań i 1453 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

43
CHANGELOG.md 100644
Wyświetl plik

@ -0,0 +1,43 @@
CHANGELOG
=========
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.
Release 6.0.2
--------------------------------------
- Solved issue when disconnecting multiple serial ports.
Release 6.0.1
--------------------------------------
- Internal serial buffer now uses [Okio](https://github.com/square/okio). This erases the 16kb write
limitation from previous versions and reduces memory footprint.
- Improved CP2102 driver and added more VID/PID pairs.
- Added a [utility class for handling the common problem of split received information in some chipsets](https://github.com/felHR85/UsbSerial/blob/master/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java).

Wyświetl plik

@ -9,10 +9,17 @@ 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)
--------------------------------------
[If UsbSerial helped you with your projects please consider donating a little sum :)](https://www.paypal.me/felhr)
Support UsbSerial
--------------------------------------
[If UsbSerial helped you with your projects please consider donating a little sum](https://www.paypal.me/felhr)\
[Or consider buying DroidTerm Pro: A Usb serial port terminal using UsbSerial](https://play.google.com/store/apps/details?id=com.felhr.droidtermpro)
Devices Supported
--------------------------------------
@ -190,7 +197,7 @@ Then add the dependency to your module's build.gradle:
/app/build.gradle
```groovy
implementation 'com.github.felHR85:UsbSerial:5.0.1'
implementation 'com.github.felHR85:UsbSerial:6.1.0'
```
TO-DO

Wyświetl plik

@ -2,10 +2,10 @@ Releasing
========
1. Change the `VERSION_NAME` value in `gradle.properties` to the version number to be released.
2. Update the `README.md` with the new version.
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

@ -12,6 +12,7 @@ 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;
@ -23,6 +24,8 @@ import java.util.Map;
public class UsbService extends Service {
public static final String TAG = "UsbService";
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";
@ -155,6 +158,8 @@ public class UsbService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
serialPort.close();
unregisterReceiver(usbReceiver);
UsbService.SERVICE_CONNECTED = false;
}
@ -174,31 +179,39 @@ public class UsbService extends Service {
// 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()) {
boolean keep = true;
// 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) {
// There is a device connected to our Android device. Try to open it as a Serial Port.
// 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();
keep = false;
break;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
if (!keep) {
// There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
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);
@ -217,6 +230,7 @@ public class UsbService extends Service {
* 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);
}

Wyświetl plik

@ -12,6 +12,7 @@ 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.SerialInputStream;
@ -25,6 +26,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class UsbService extends Service {
public static final String TAG = "UsbService";
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";
@ -126,6 +129,8 @@ public class UsbService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
serialPort.close();
unregisterReceiver(usbReceiver);
UsbService.SERVICE_CONNECTED = false;
}
@ -154,30 +159,39 @@ public class UsbService extends Service {
// 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()) {
boolean keep = true;
// first, dump the map 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)) {
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003)) {
if (UsbSerialDevice.isSupported(device)) {
// There is a device connected to our Android device. Try to open it as a Serial Port.
requestUserPermission();
keep = false;
break;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
if (!keep) {
// There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
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);
@ -196,6 +210,7 @@ public class UsbService extends Service {
* 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);
}
@ -293,4 +308,4 @@ public class UsbService extends Service {
this.keep.set(keep);
}
}
}
}

Wyświetl plik

@ -12,6 +12,7 @@ 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;
@ -23,6 +24,8 @@ import java.util.Map;
public class UsbService extends Service {
public static final String TAG = "UsbService";
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";
@ -156,6 +159,8 @@ public class UsbService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
serialPort.close();
unregisterReceiver(usbReceiver);
UsbService.SERVICE_CONNECTED = false;
}
@ -184,30 +189,39 @@ public class UsbService extends Service {
// 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()) {
boolean keep = true;
// first, dump the map 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)) {
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003)) {
if (UsbSerialDevice.isSupported(device)) {
// There is a device connected to our Android device. Try to open it as a Serial Port.
requestUserPermission();
keep = false;
break;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
if (!keep) {
if (device==null) {
// There is 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);
@ -226,6 +240,7 @@ public class UsbService extends Service {
* 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);
}

Wyświetl plik

@ -1,4 +1,4 @@
VERSION_NAME=5.0.1
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
@ -36,6 +37,14 @@ android {
dependencies {
implementation 'com.annimon:stream:1.2.1'
implementation 'com.squareup.okio:okio:2.1.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'
}
createJar.dependsOn(deleteJar, build)

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

@ -0,0 +1,188 @@
package com.felhr.tests.usbserial;
import com.felhr.usbserial.SerialBuffer;
import junit.framework.TestCase;
import org.junit.Assert;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
public class SerialBufferTest extends TestCase {
private static final int BIG_BUFFER_1_SIZE = 64 * 1024;
private static final int BIG_BUFFER_2_SIZE = 1024 * 1024;
private static final int READ_BUFFER_SIZE = 16 * 1024;
private static final String text1 = "HOLA";
private static final byte[] bigBuffer = new byte[BIG_BUFFER_1_SIZE];
private static final byte[] bigBuffer2 = new byte[BIG_BUFFER_2_SIZE];
private static final byte[] bigReadBuffer = new byte[READ_BUFFER_SIZE];
private SerialBuffer serialBuffer;
// Testing Write buffer
@Test
public void testSimpleWriteBuffer(){
serialBuffer = new SerialBuffer(true);
serialBuffer.putWriteBuffer(text1.getBytes());
byte[] dataReceived = serialBuffer.getWriteBuffer();
assertEquals(text1, new String(dataReceived));
}
@Test
public void testBigSimpleWriteBuffer(){
try {
new Random().nextBytes(bigBuffer);
serialBuffer = new SerialBuffer(true);
serialBuffer.putWriteBuffer(bigBuffer);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
while(outputStream.size() < bigBuffer.length){
byte[] srcData = serialBuffer.getWriteBuffer();
outputStream.write(srcData);
}
byte[] srcBuffered = outputStream.toByteArray();
Assert.assertArrayEquals(bigBuffer, srcBuffered);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testSuperBigSimpleWriteBuffer(){
try {
new Random().nextBytes(bigBuffer2);
serialBuffer = new SerialBuffer(true);
serialBuffer.putWriteBuffer(bigBuffer2);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
while(outputStream.size() < bigBuffer2.length){
byte[] srcData = serialBuffer.getWriteBuffer();
outputStream.write(srcData);
}
byte[] srcBuffered = outputStream.toByteArray();
Assert.assertArrayEquals(bigBuffer2, srcBuffered);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testSimpleWriteBufferAsync1(){
try {
new Random().nextBytes(bigBuffer2);
serialBuffer = new SerialBuffer(true);
WriterThread writerThread = new WriterThread(serialBuffer, bigBuffer2);
writerThread.start();
while(writerThread.getState() != Thread.State.TERMINATED){/*Busy waiting*/}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
while(outputStream.size() < bigBuffer2.length){
byte[] srcData = serialBuffer.getWriteBuffer();
outputStream.write(srcData);
}
byte[] dataReceived = outputStream.toByteArray();
Assert.assertArrayEquals(bigBuffer2, dataReceived);
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testSimpleWriteBufferAsync2(){
try {
new Random().nextBytes(bigBuffer2);
serialBuffer = new SerialBuffer(true);
WriterThread writerThread = new WriterThread(serialBuffer, bigBuffer2, Thread.currentThread());
writerThread.start();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
while(outputStream.size() < bigBuffer2.length){
byte[] srcData = serialBuffer.getWriteBuffer();
outputStream.write(srcData);
}
byte[] dataReceived = outputStream.toByteArray();
Assert.assertArrayEquals(bigBuffer2, dataReceived);
} catch (IOException e) {
e.printStackTrace();
}
}
// Testing ReadBuffer
@Test
public void testReadBuffer(){
new Random().nextBytes(bigReadBuffer);
serialBuffer = new SerialBuffer(true);
ByteBuffer readBuffer = serialBuffer.getReadBuffer();
readBuffer.put(bigReadBuffer);
byte[] buffered = serialBuffer.getDataReceived();
Assert.assertArrayEquals(bigReadBuffer, buffered);
}
@Test
public void testReadBufferCompatible(){
new Random().nextBytes(bigReadBuffer);
serialBuffer = new SerialBuffer(false);
byte[] readBuffer = serialBuffer.getBufferCompatible();
System.arraycopy(bigReadBuffer, 0, readBuffer, 0, bigReadBuffer.length);
byte[] buffered = serialBuffer.getDataReceivedCompatible(bigReadBuffer.length);
Assert.assertArrayEquals(bigReadBuffer, buffered);
}
private class WriterThread extends Thread{
private SerialBuffer serialBuffer;
private byte[] data;
private Thread callerThread;
public WriterThread(SerialBuffer serialBuffer, byte[] data){
this.serialBuffer = serialBuffer;
this.data = data;
}
public WriterThread(SerialBuffer serialBuffer, byte[] data, Thread callerThread){
this.serialBuffer = serialBuffer;
this.data = data;
this.callerThread = callerThread;
}
@Override
public void run() {
if(callerThread == null) {
serialBuffer.putWriteBuffer(data);
}else{
while(callerThread.getState() != State.WAITING){/*Busy waiting*/ }
serialBuffer.putWriteBuffer(data);
}
}
}
}

Wyświetl plik

@ -0,0 +1,214 @@
package com.felhr.tests.utils;
import com.felhr.utils.ProtocolBuffer;
import junit.framework.TestCase;
import org.junit.Assert;
import org.junit.Test;
public class ProtocolBufferTest extends TestCase {
private final String onePacket = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n";
private final String twoPackets = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n";
private final String splitPacket = "$GPAAM,A,A,0.10,N,WPTN";
private final String oneHalfPacket = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000";
private final String[] verySplit ={"$GPAAM,",
"A",
",",
"A,",
"0",
".",
"10,N",
",WPTNME*32\r\n"};
private final byte[] rawPacket = new byte[]{0x21, 0x3b, 0x20, 0x40};
private final byte[] twoRawPackets = new byte[]{0x21, 0x3b, 0x20, 0x40, 0x4a, 0x20, 0x40};
private final byte[] splitRawPacket = new byte[]{0x21, 0x3b, 0x20, 0x40, 0x4a};
private final byte[][] verySplitRawPacket = {
new byte[]{0x21},
new byte[]{0x3b},
new byte[]{0x20},
new byte[]{0x40}};
private ProtocolBuffer protocolBuffer;
private final String modeText = ProtocolBuffer.TEXT;
private final String modeBinary = ProtocolBuffer.BINARY;
@Test
public void testOnePacket(){
protocolBuffer = new ProtocolBuffer(modeText);
protocolBuffer.setDelimiter("\r\n");
protocolBuffer.appendData(onePacket.getBytes());
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
String nextCommand = protocolBuffer.nextTextCommand();
assertEquals(onePacket, nextCommand);
}
@Test
public void testTwoPackets(){
protocolBuffer = new ProtocolBuffer(modeText);
protocolBuffer.setDelimiter("\r\n");
protocolBuffer.appendData(twoPackets.getBytes());
StringBuilder builder = new StringBuilder();
while(protocolBuffer.hasMoreCommands()){
builder.append(protocolBuffer.nextTextCommand());
}
assertEquals(twoPackets, builder.toString());
}
@Test
public void testSplitPackets(){
protocolBuffer = new ProtocolBuffer(modeText);
protocolBuffer.setDelimiter("\r\n");
protocolBuffer.appendData(splitPacket.getBytes());
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
}
@Test
public void testOneHalfPacket(){
protocolBuffer = new ProtocolBuffer(modeText);
protocolBuffer.setDelimiter("\r\n");
protocolBuffer.appendData(oneHalfPacket.getBytes());
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
String nextCommand = protocolBuffer.nextTextCommand();
assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", nextCommand);
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
nextCommand = protocolBuffer.nextTextCommand();
assertNull(nextCommand);
}
@Test
public void testVerySplit(){
protocolBuffer = new ProtocolBuffer(modeText);
protocolBuffer.setDelimiter("\r\n");
protocolBuffer.appendData(verySplit[0].getBytes());
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[1].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[2].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[3].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[4].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[5].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[6].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplit[7].getBytes());
hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
String command = protocolBuffer.nextTextCommand();
assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", command);
}
@Test
public void testRawPacket(){
protocolBuffer = new ProtocolBuffer(modeBinary);
protocolBuffer.setDelimiter(new byte[]{0x20, 0x40});
protocolBuffer.appendData(rawPacket);
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
byte[] command = protocolBuffer.nextBinaryCommand();
Assert.assertArrayEquals(command, rawPacket);
command = protocolBuffer.nextBinaryCommand();
assertNull(command);
}
@Test
public void testTwoRawPackets(){
protocolBuffer = new ProtocolBuffer(modeBinary);
protocolBuffer.setDelimiter(new byte[]{0x20, 0x40});
protocolBuffer.appendData(twoRawPackets);
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
byte[] command1 = protocolBuffer.nextBinaryCommand();
Assert.assertArrayEquals(command1, new byte[]{0x21, 0x3b, 0x20, 0x40});
hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
byte[] command2 = protocolBuffer.nextBinaryCommand();
Assert.assertArrayEquals(command2, new byte[]{0x4a, 0x20, 0x40});
command2 = protocolBuffer.nextBinaryCommand();
assertNull(command2);
}
@Test
public void testSplitRawPacket(){
protocolBuffer = new ProtocolBuffer(modeBinary);
protocolBuffer.setDelimiter(new byte[]{0x20, 0x40});
protocolBuffer.appendData(splitRawPacket);
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
byte[] command1 = protocolBuffer.nextBinaryCommand();
Assert.assertArrayEquals(command1, new byte[]{0x21, 0x3b, 0x20, 0x40});
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
}
@Test
public void testVerySplitRawPacket(){
protocolBuffer = new ProtocolBuffer(modeBinary);
protocolBuffer.setDelimiter(new byte[]{0x20, 0x40});
protocolBuffer.appendData(verySplitRawPacket[0]);
boolean hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplitRawPacket[1]);
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplitRawPacket[2]);
hasMoreData = protocolBuffer.hasMoreCommands();
assertFalse(hasMoreData);
protocolBuffer.appendData(verySplitRawPacket[3]);
hasMoreData = protocolBuffer.hasMoreCommands();
assertTrue(hasMoreData);
byte[] command = protocolBuffer.nextBinaryCommand();
Assert.assertArrayEquals(command, new byte[]{0x21, 0x3b, 0x20, 0x40});
}
}

Wyświetl plik

@ -1,5 +1,8 @@
package com.felhr.deviceids;
import static com.felhr.deviceids.Helpers.createTable;
import static com.felhr.deviceids.Helpers.createDevice;
public class CH34xIds
{
private CH34xIds()
@ -7,34 +10,15 @@ public class CH34xIds
}
private static final ConcreteDevice[] ch34xDevices = new ConcreteDevice[]
{
new ConcreteDevice(0x4348, 0x5523),
new ConcreteDevice(0x1a86, 0x7523),
new ConcreteDevice(0x1a86, 0x5523),
new ConcreteDevice(0x1a86, 0x0445)
};
private static final long[] ch34xDevices = createTable(
createDevice(0x4348, 0x5523),
createDevice(0x1a86, 0x7523),
createDevice(0x1a86, 0x5523),
createDevice(0x1a86, 0x0445)
);
public static boolean isDeviceSupported(int vendorId, int productId)
{
for(int i=0;i<=ch34xDevices.length-1;i++)
{
if(ch34xDevices[i].vendorId == vendorId &&ch34xDevices[i].productId == productId )
return true;
}
return false;
return Helpers.exists(ch34xDevices, vendorId, productId);
}
private static class ConcreteDevice
{
public int vendorId;
public int productId;
public ConcreteDevice(int vendorId, int productId)
{
this.vendorId = vendorId;
this.productId = productId;
}
}
}

Wyświetl plik

@ -1,169 +1,155 @@
package com.felhr.deviceids;
import static com.felhr.deviceids.Helpers.createTable;
import static com.felhr.deviceids.Helpers.createDevice;
public class CP210xIds
{
/* Different products and vendors of CP210x family
// From current cp210x linux driver:
https://github.com/torvalds/linux/blob/164c09978cebebd8b5fc198e9243777dbaecdfa0/drivers/usb/serial/cp210x.c
*/
private static final ConcreteDevice[] cp210xDevices = new ConcreteDevice[]
{
new ConcreteDevice(0x045B, 0x0053),
new ConcreteDevice(0x0471, 0x066A),
new ConcreteDevice(0x0489, 0xE000),
new ConcreteDevice(0x0489, 0xE003),
new ConcreteDevice(0x0745, 0x1000),
new ConcreteDevice(0x0846, 0x1100),
new ConcreteDevice(0x08e6, 0x5501),
new ConcreteDevice(0x08FD, 0x000A),
new ConcreteDevice(0x0BED, 0x1100),
new ConcreteDevice(0x0BED, 0x1101),
new ConcreteDevice(0x0FCF, 0x1003),
new ConcreteDevice(0x0FCF, 0x1004),
new ConcreteDevice(0x0FCF, 0x1006),
new ConcreteDevice(0x0FDE, 0xCA05),
new ConcreteDevice(0x10A6, 0xAA26),
new ConcreteDevice(0x10AB, 0x10C5),
new ConcreteDevice(0x10B5, 0xAC70),
new ConcreteDevice(0x10C4, 0x0F91),
new ConcreteDevice(0x10C4, 0x1101),
new ConcreteDevice(0x10C4, 0x1601),
new ConcreteDevice(0x10C4, 0x800A),
new ConcreteDevice(0x10C4, 0x803B),
new ConcreteDevice(0x10C4, 0x8044),
new ConcreteDevice(0x10C4, 0x804E),
new ConcreteDevice(0x10C4, 0x8053),
new ConcreteDevice(0x10C4, 0x8054),
new ConcreteDevice(0x10C4, 0x8066),
new ConcreteDevice(0x10C4, 0x806F),
new ConcreteDevice(0x10C4, 0x807A),
new ConcreteDevice(0x10C4, 0x80C4),
new ConcreteDevice(0x10C4, 0x80CA),
new ConcreteDevice(0x10C4, 0x80DD),
new ConcreteDevice(0x10C4, 0x80F6),
new ConcreteDevice(0x10C4, 0x8115),
new ConcreteDevice(0x10C4, 0x813D),
new ConcreteDevice(0x10C4, 0x813F),
new ConcreteDevice(0x10C4, 0x814A),
new ConcreteDevice(0x10C4, 0x814B),
new ConcreteDevice(0x2405, 0x0003),
new ConcreteDevice(0x10C4, 0x8156),
new ConcreteDevice(0x10C4, 0x815E),
new ConcreteDevice(0x10C4, 0x815F),
new ConcreteDevice(0x10C4, 0x818B),
new ConcreteDevice(0x10C4, 0x819F),
new ConcreteDevice(0x10C4, 0x81A6),
new ConcreteDevice(0x10C4, 0x81A9),
new ConcreteDevice(0x10C4, 0x81AC),
new ConcreteDevice(0x10C4, 0x81AD),
new ConcreteDevice(0x10C4, 0x81C8),
new ConcreteDevice(0x10C4, 0x81E2),
new ConcreteDevice(0x10C4, 0x81E7),
new ConcreteDevice(0x10C4, 0x81E8),
new ConcreteDevice(0x10C4, 0x81F2),
new ConcreteDevice(0x10C4, 0x8218),
new ConcreteDevice(0x10C4, 0x822B),
new ConcreteDevice(0x10C4, 0x826B),
new ConcreteDevice(0x10C4, 0x8281),
new ConcreteDevice(0x10C4, 0x8293),
new ConcreteDevice(0x10C4, 0x82F9),
new ConcreteDevice(0x10C4, 0x8341),
new ConcreteDevice(0x10C4, 0x8382),
new ConcreteDevice(0x10C4, 0x83A8),
new ConcreteDevice(0x10C4, 0x83D8),
new ConcreteDevice(0x10C4, 0x8411),
new ConcreteDevice(0x10C4, 0x8418),
new ConcreteDevice(0x10C4, 0x846E),
new ConcreteDevice(0x10C4, 0x8477),
new ConcreteDevice(0x10C4, 0x85EA),
new ConcreteDevice(0x10C4, 0x85EB),
new ConcreteDevice(0x10C4, 0x85F8),
new ConcreteDevice(0x10C4, 0x8664),
new ConcreteDevice(0x10C4, 0x8665),
new ConcreteDevice(0x10C4, 0x875C),
new ConcreteDevice(0x10C4, 0x88A4),
new ConcreteDevice(0x10C4, 0x88A5),
new ConcreteDevice(0x10C4, 0xEA60),
new ConcreteDevice(0x10C4, 0xEA61),
new ConcreteDevice(0x10C4, 0xEA70),
new ConcreteDevice(0x10C4, 0xEA80),
new ConcreteDevice(0x10C4, 0xEA71),
new ConcreteDevice(0x10C4, 0xF001),
new ConcreteDevice(0x10C4, 0xF002),
new ConcreteDevice(0x10C4, 0xF003),
new ConcreteDevice(0x10C4, 0xF004),
new ConcreteDevice(0x10C5, 0xEA61),
new ConcreteDevice(0x10CE, 0xEA6A),
new ConcreteDevice(0x13AD, 0x9999),
new ConcreteDevice(0x1555, 0x0004),
new ConcreteDevice(0x166A, 0x0201),
new ConcreteDevice(0x166A, 0x0301),
new ConcreteDevice(0x166A, 0x0303),
new ConcreteDevice(0x166A, 0x0304),
new ConcreteDevice(0x166A, 0x0305),
new ConcreteDevice(0x166A, 0x0401),
new ConcreteDevice(0x166A, 0x0101),
new ConcreteDevice(0x16D6, 0x0001),
new ConcreteDevice(0x16DC, 0x0010),
new ConcreteDevice(0x16DC, 0x0011),
new ConcreteDevice(0x16DC, 0x0012),
new ConcreteDevice(0x16DC, 0x0015),
new ConcreteDevice(0x17A8, 0x0001),
new ConcreteDevice(0x17A8, 0x0005),
new ConcreteDevice(0x17F4, 0xAAAA),
new ConcreteDevice(0x1843, 0x0200),
new ConcreteDevice(0x18EF, 0xE00F),
new ConcreteDevice(0x1ADB, 0x0001),
new ConcreteDevice(0x1BE3, 0x07A6),
new ConcreteDevice(0x1E29, 0x0102),
new ConcreteDevice(0x1E29, 0x0501),
new ConcreteDevice(0x1FB9, 0x0100),
new ConcreteDevice(0x1FB9, 0x0200),
new ConcreteDevice(0x1FB9, 0x0201),
new ConcreteDevice(0x1FB9, 0x0202),
new ConcreteDevice(0x1FB9, 0x0203),
new ConcreteDevice(0x1FB9, 0x0300),
new ConcreteDevice(0x1FB9, 0x0301),
new ConcreteDevice(0x1FB9, 0x0302),
new ConcreteDevice(0x1FB9, 0x0303),
new ConcreteDevice(0x1FB9, 0x0400),
new ConcreteDevice(0x1FB9, 0x0401),
new ConcreteDevice(0x1FB9, 0x0402),
new ConcreteDevice(0x1FB9, 0x0403),
new ConcreteDevice(0x1FB9, 0x0404),
new ConcreteDevice(0x1FB9, 0x0600),
new ConcreteDevice(0x1FB9, 0x0601),
new ConcreteDevice(0x1FB9, 0x0602),
new ConcreteDevice(0x1FB9, 0x0700),
new ConcreteDevice(0x1FB9, 0x0701),
new ConcreteDevice(0x3195, 0xF190),
new ConcreteDevice(0x3195, 0xF280),
new ConcreteDevice(0x3195, 0xF281),
new ConcreteDevice(0x413C, 0x9500)
};
private static final long[] cp210xDevices = createTable(
createDevice(0x045B, 0x0053),
createDevice(0x0471, 0x066A),
createDevice(0x0489, 0xE000),
createDevice(0x0489, 0xE003),
createDevice(0x0745, 0x1000),
createDevice(0x0846, 0x1100),
createDevice(0x08e6, 0x5501),
createDevice(0x08FD, 0x000A),
createDevice(0x0BED, 0x1100),
createDevice(0x0BED, 0x1101),
createDevice(0x0FCF, 0x1003),
createDevice(0x0FCF, 0x1004),
createDevice(0x0FCF, 0x1006),
createDevice(0x0FDE, 0xCA05),
createDevice(0x10A6, 0xAA26),
createDevice(0x10AB, 0x10C5),
createDevice(0x10B5, 0xAC70),
createDevice(0x10C4, 0x0F91),
createDevice(0x10C4, 0x1101),
createDevice(0x10C4, 0x1601),
createDevice(0x10C4, 0x800A),
createDevice(0x10C4, 0x803B),
createDevice(0x10C4, 0x8044),
createDevice(0x10C4, 0x804E),
createDevice(0x10C4, 0x8053),
createDevice(0x10C4, 0x8054),
createDevice(0x10C4, 0x8066),
createDevice(0x10C4, 0x806F),
createDevice(0x10C4, 0x807A),
createDevice(0x10C4, 0x80C4),
createDevice(0x10C4, 0x80CA),
createDevice(0x10C4, 0x80DD),
createDevice(0x10C4, 0x80F6),
createDevice(0x10C4, 0x8115),
createDevice(0x10C4, 0x813D),
createDevice(0x10C4, 0x813F),
createDevice(0x10C4, 0x814A),
createDevice(0x10C4, 0x814B),
createDevice(0x2405, 0x0003),
createDevice(0x10C4, 0x8156),
createDevice(0x10C4, 0x815E),
createDevice(0x10C4, 0x815F),
createDevice(0x10C4, 0x818B),
createDevice(0x10C4, 0x819F),
createDevice(0x10C4, 0x81A6),
createDevice(0x10C4, 0x81A9),
createDevice(0x10C4, 0x81AC),
createDevice(0x10C4, 0x81AD),
createDevice(0x10C4, 0x81C8),
createDevice(0x10C4, 0x81E2),
createDevice(0x10C4, 0x81E7),
createDevice(0x10C4, 0x81E8),
createDevice(0x10C4, 0x81F2),
createDevice(0x10C4, 0x8218),
createDevice(0x10C4, 0x822B),
createDevice(0x10C4, 0x826B),
createDevice(0x10C4, 0x8281),
createDevice(0x10C4, 0x8293),
createDevice(0x10C4, 0x82F9),
createDevice(0x10C4, 0x8341),
createDevice(0x10C4, 0x8382),
createDevice(0x10C4, 0x83A8),
createDevice(0x10C4, 0x83D8),
createDevice(0x10C4, 0x8411),
createDevice(0x10C4, 0x8418),
createDevice(0x10C4, 0x846E),
createDevice(0x10C4, 0x8477),
createDevice(0x10C4, 0x85EA),
createDevice(0x10C4, 0x85EB),
createDevice(0x10C4, 0x85F8),
createDevice(0x10C4, 0x8664),
createDevice(0x10C4, 0x8665),
createDevice(0x10C4, 0x875C),
createDevice(0x10C4, 0x88A4),
createDevice(0x10C4, 0x88A5),
createDevice(0x10C4, 0xEA60),
createDevice(0x10C4, 0xEA61),
createDevice(0x10C4, 0xEA63),
createDevice(0x10C4, 0xEA70),
createDevice(0x10C4, 0xEA71),
createDevice(0x10C4, 0xEA7A),
createDevice(0x10C4, 0xEA7B),
createDevice(0x10C4, 0xEA80),
createDevice(0x10C4, 0xF001),
createDevice(0x10C4, 0xF002),
createDevice(0x10C4, 0xF003),
createDevice(0x10C4, 0xF004),
createDevice(0x10C5, 0xEA61),
createDevice(0x10CE, 0xEA6A),
createDevice(0x13AD, 0x9999),
createDevice(0x1555, 0x0004),
createDevice(0x166A, 0x0201),
createDevice(0x166A, 0x0301),
createDevice(0x166A, 0x0303),
createDevice(0x166A, 0x0304),
createDevice(0x166A, 0x0305),
createDevice(0x166A, 0x0401),
createDevice(0x166A, 0x0101),
createDevice(0x16D6, 0x0001),
createDevice(0x16DC, 0x0010),
createDevice(0x16DC, 0x0011),
createDevice(0x16DC, 0x0012),
createDevice(0x16DC, 0x0015),
createDevice(0x17A8, 0x0001),
createDevice(0x17A8, 0x0005),
createDevice(0x17F4, 0xAAAA),
createDevice(0x1843, 0x0200),
createDevice(0x18EF, 0xE00F),
createDevice(0x1ADB, 0x0001),
createDevice(0x1BE3, 0x07A6),
createDevice(0x1E29, 0x0102),
createDevice(0x1E29, 0x0501),
createDevice(0x1FB9, 0x0100),
createDevice(0x1FB9, 0x0200),
createDevice(0x1FB9, 0x0201),
createDevice(0x1FB9, 0x0202),
createDevice(0x1FB9, 0x0203),
createDevice(0x1FB9, 0x0300),
createDevice(0x1FB9, 0x0301),
createDevice(0x1FB9, 0x0302),
createDevice(0x1FB9, 0x0303),
createDevice(0x1FB9, 0x0400),
createDevice(0x1FB9, 0x0401),
createDevice(0x1FB9, 0x0402),
createDevice(0x1FB9, 0x0403),
createDevice(0x1FB9, 0x0404),
createDevice(0x1FB9, 0x0600),
createDevice(0x1FB9, 0x0601),
createDevice(0x1FB9, 0x0602),
createDevice(0x1FB9, 0x0700),
createDevice(0x1FB9, 0x0701),
createDevice(0x3195, 0xF190),
createDevice(0x3195, 0xF280),
createDevice(0x3195, 0xF281),
createDevice(0x413C, 0x9500),
createDevice(0x1908, 0x2311) //serial of CMOS camera
);
public static boolean isDeviceSupported(int vendorId, int productId)
{
for(int i=0;i<=cp210xDevices.length-1;i++)
{
if(cp210xDevices[i].vendorId == vendorId && cp210xDevices[i].productId == productId )
{
return true;
}
}
return false;
return Helpers.exists(cp210xDevices, vendorId, productId);
}
private static class ConcreteDevice
{
public int vendorId;
public int productId;
public ConcreteDevice(int vendorId, int productId)
{
this.vendorId = vendorId;
this.productId = productId;
}
}
}

Wyświetl plik

@ -1,32 +1,16 @@
package com.felhr.deviceids;
import static com.felhr.deviceids.Helpers.createTable;
import static com.felhr.deviceids.Helpers.createDevice;
public class CP2130Ids
{
private static final ConcreteDevice[] cp2130Devices = new ConcreteDevice[]{
new ConcreteDevice(0x10C4, 0x87a0),
};
private static final long[] cp2130Devices = createTable(
createDevice(0x10C4, 0x87a0)
);
public static boolean isDeviceSupported(int vendorId, int productId)
{
for(int i=0;i<=cp2130Devices.length-1;i++)
{
if(cp2130Devices[i].vendorId == vendorId && cp2130Devices[i].productId == productId )
{
return true;
}
}
return false;
}
private static class ConcreteDevice
{
public int vendorId;
public int productId;
public ConcreteDevice(int vendorId, int productId)
{
this.vendorId = vendorId;
this.productId = productId;
}
return Helpers.exists(cp2130Devices, vendorId, productId);
}
}

Wyświetl plik

@ -0,0 +1,26 @@
package com.felhr.deviceids;
import java.util.Arrays;
class Helpers {
/**
* Create a device id, since they are 4 bytes each, we can pack the pair in an long.
*/
static long createDevice(int vendorId, int productId) {
return ((long) vendorId) << 32 | (productId & 0xFFFF_FFFFL);
}
/**
* Creates a sorted table.
* This way, we can use binarySearch to find whether the entry exists.
*/
static long[] createTable(long ... entries) {
Arrays.sort(entries);
return entries;
}
static boolean exists(long[] devices, int vendorId, int productId) {
return Arrays.binarySearch(devices, createDevice(vendorId, productId)) >= 0;
}
}

Wyświetl plik

@ -1,5 +1,8 @@
package com.felhr.deviceids;
import static com.felhr.deviceids.Helpers.createTable;
import static com.felhr.deviceids.Helpers.createDevice;
public class PL2303Ids
{
private PL2303Ids()
@ -7,87 +10,68 @@ public class PL2303Ids
}
private static final ConcreteDevice[] pl2303Devices = new ConcreteDevice[]
{
new ConcreteDevice (0x04a5, 0x4027),
new ConcreteDevice (0x067b, 0x2303),
new ConcreteDevice (0x067b, 0x04bb),
new ConcreteDevice (0x067b, 0x1234),
new ConcreteDevice (0x067b, 0xaaa0),
new ConcreteDevice (0x067b, 0xaaa2),
new ConcreteDevice (0x067b, 0x0611),
new ConcreteDevice (0x067b, 0x0612),
new ConcreteDevice (0x067b, 0x0609),
new ConcreteDevice (0x067b, 0x331a),
new ConcreteDevice (0x067b, 0x0307),
new ConcreteDevice (0x067b, 0x0463),
new ConcreteDevice (0x0557, 0x2008),
new ConcreteDevice (0x0547, 0x2008),
new ConcreteDevice (0x04bb, 0x0a03),
new ConcreteDevice (0x04bb, 0x0a0e),
new ConcreteDevice (0x056e, 0x5003),
new ConcreteDevice (0x056e, 0x5004),
new ConcreteDevice (0x0eba, 0x1080),
new ConcreteDevice (0x0eba, 0x2080),
new ConcreteDevice (0x0df7, 0x0620),
new ConcreteDevice (0x0584, 0xb000),
new ConcreteDevice (0x2478, 0x2008),
new ConcreteDevice (0x1453, 0x4026),
new ConcreteDevice (0x0731, 0x0528),
new ConcreteDevice (0x6189, 0x2068),
new ConcreteDevice (0x11f7, 0x02df),
new ConcreteDevice (0x04e8, 0x8001),
new ConcreteDevice (0x11f5, 0x0001),
new ConcreteDevice (0x11f5, 0x0003),
new ConcreteDevice (0x11f5, 0x0004),
new ConcreteDevice (0x11f5, 0x0005),
new ConcreteDevice (0x0745, 0x0001),
new ConcreteDevice (0x078b, 0x1234),
new ConcreteDevice (0x10b5, 0xac70),
new ConcreteDevice (0x079b, 0x0027),
new ConcreteDevice (0x0413, 0x2101),
new ConcreteDevice (0x0e55, 0x110b),
new ConcreteDevice (0x0731, 0x2003),
new ConcreteDevice (0x050d, 0x0257),
new ConcreteDevice (0x058f, 0x9720),
new ConcreteDevice (0x11f6, 0x2001),
new ConcreteDevice (0x07aa, 0x002a),
new ConcreteDevice (0x05ad, 0x0fba),
new ConcreteDevice (0x5372, 0x2303),
new ConcreteDevice (0x03f0, 0x0b39),
new ConcreteDevice (0x03f0, 0x3139),
new ConcreteDevice (0x03f0, 0x3239),
new ConcreteDevice (0x03f0, 0x3524),
new ConcreteDevice (0x04b8, 0x0521),
new ConcreteDevice (0x04b8, 0x0522),
new ConcreteDevice (0x054c, 0x0437),
new ConcreteDevice (0x11ad, 0x0001),
new ConcreteDevice (0x0b63, 0x6530),
new ConcreteDevice (0x0b8c, 0x2303),
new ConcreteDevice (0x110a, 0x1150),
new ConcreteDevice (0x0557, 0x2008)
};
private static final long[] pl2303Devices = createTable(
createDevice(0x04a5, 0x4027),
createDevice(0x067b, 0x2303),
createDevice(0x067b, 0x04bb),
createDevice(0x067b, 0x1234),
createDevice(0x067b, 0xaaa0),
createDevice(0x067b, 0xaaa2),
createDevice(0x067b, 0x0611),
createDevice(0x067b, 0x0612),
createDevice(0x067b, 0x0609),
createDevice(0x067b, 0x331a),
createDevice(0x067b, 0x0307),
createDevice(0x067b, 0x0463),
createDevice(0x0557, 0x2008),
createDevice(0x0547, 0x2008),
createDevice(0x04bb, 0x0a03),
createDevice(0x04bb, 0x0a0e),
createDevice(0x056e, 0x5003),
createDevice(0x056e, 0x5004),
createDevice(0x0eba, 0x1080),
createDevice(0x0eba, 0x2080),
createDevice(0x0df7, 0x0620),
createDevice(0x0584, 0xb000),
createDevice(0x2478, 0x2008),
createDevice(0x1453, 0x4026),
createDevice(0x0731, 0x0528),
createDevice(0x6189, 0x2068),
createDevice(0x11f7, 0x02df),
createDevice(0x04e8, 0x8001),
createDevice(0x11f5, 0x0001),
createDevice(0x11f5, 0x0003),
createDevice(0x11f5, 0x0004),
createDevice(0x11f5, 0x0005),
createDevice(0x0745, 0x0001),
createDevice(0x078b, 0x1234),
createDevice(0x10b5, 0xac70),
createDevice(0x079b, 0x0027),
createDevice(0x0413, 0x2101),
createDevice(0x0e55, 0x110b),
createDevice(0x0731, 0x2003),
createDevice(0x050d, 0x0257),
createDevice(0x058f, 0x9720),
createDevice(0x11f6, 0x2001),
createDevice(0x07aa, 0x002a),
createDevice(0x05ad, 0x0fba),
createDevice(0x5372, 0x2303),
createDevice(0x03f0, 0x0b39),
createDevice(0x03f0, 0x3139),
createDevice(0x03f0, 0x3239),
createDevice(0x03f0, 0x3524),
createDevice(0x04b8, 0x0521),
createDevice(0x04b8, 0x0522),
createDevice(0x054c, 0x0437),
createDevice(0x11ad, 0x0001),
createDevice(0x0b63, 0x6530),
createDevice(0x0b8c, 0x2303),
createDevice(0x110a, 0x1150),
createDevice(0x0557, 0x2008)
);
public static boolean isDeviceSupported(int vendorId, int productId)
{
for(int i=0;i<=pl2303Devices.length-1;i++)
{
if(pl2303Devices[i].vendorId == vendorId && pl2303Devices[i].productId == productId )
return true;
}
return false;
}
private static class ConcreteDevice
{
public int vendorId;
public int productId;
public ConcreteDevice(int vendorId, int productId)
{
this.vendorId = vendorId;
this.productId = productId;
}
return Helpers.exists(pl2303Devices, vendorId, productId);
}
}

Wyświetl plik

@ -1,5 +1,8 @@
package com.felhr.deviceids;
import static com.felhr.deviceids.Helpers.createTable;
import static com.felhr.deviceids.Helpers.createDevice;
public class XdcVcpIds
{
/*
@ -8,35 +11,14 @@ public class XdcVcpIds
/* Different products and vendors of XdcVcp family
*/
private static final ConcreteDevice[] xdcvcpDevices = new ConcreteDevice[]
{
new ConcreteDevice(0x264D, 0x0232), // VCP (Virtual Com Port)
new ConcreteDevice(0x264D, 0x0120), // USI (Universal Sensor Interface)
new ConcreteDevice(0x0483, 0x5740) //CC3D (STM)
};
private static final long[] xdcvcpDevices = createTable(
createDevice(0x264D, 0x0232), // VCP (Virtual Com Port)
createDevice(0x264D, 0x0120), // USI (Universal Sensor Interface)
createDevice(0x0483, 0x5740) //CC3D (STM)
);
public static boolean isDeviceSupported(int vendorId, int productId)
{
for(int i=0;i<=xdcvcpDevices.length-1;i++)
{
if(xdcvcpDevices[i].vendorId == vendorId && xdcvcpDevices[i].productId == productId )
{
return true;
}
}
return false;
return Helpers.exists(xdcvcpDevices, vendorId, productId);
}
private static class ConcreteDevice
{
public int vendorId;
public int productId;
public ConcreteDevice(int vendorId, int productId)
{
this.vendorId = vendorId;
this.productId = productId;
}
}
}

Wyświetl plik

@ -0,0 +1,26 @@
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() {
if (!this.keep) {
return;
}
this.workingThread = Thread.currentThread();
while (this.keep && (!this.workingThread.isInterrupted())) {
doRun();
}
}
abstract void doRun();
}

Wyświetl plik

@ -41,10 +41,9 @@ public class BLED112SerialDevice extends UsbSerialDevice
private static final int BLED112_DEFAULT_CONTROL_LINE = 0x0003;
private static final int BLED112_DISCONNECT_CONTROL_LINE = 0x0002;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
@Deprecated
public BLED112SerialDevice(UsbDevice device, UsbDeviceConnection connection)
@ -88,7 +87,7 @@ public class BLED112SerialDevice extends UsbSerialDevice
setControlCommand(BLED112_SET_CONTROL_LINE_STATE, BLED112_DEFAULT_CONTROL_LINE, null);
// Initialize UsbRequest
requestIN = new UsbRequest();
UsbRequest requestIN = new UsbRequest();
requestIN.initialize(connection, inEndpoint);
// Pass references to the threads
@ -204,6 +203,12 @@ public class BLED112SerialDevice extends UsbSerialDevice
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -46,10 +46,10 @@ public class CDCSerialDevice extends UsbSerialDevice
private static final int CDC_CONTROL_LINE_ON = 0x0003;
private static final int CDC_CONTROL_LINE_OFF = 0x0000;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
private int cdcControl = 0;
private int initialBaudRate = 0;
@ -63,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));
}
@ -84,7 +85,7 @@ public class CDCSerialDevice extends UsbSerialDevice
if(ret)
{
// Initialize UsbRequest
requestIN = new SafeUsbRequest();
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
@ -246,6 +247,12 @@ public class CDCSerialDevice extends UsbSerialDevice
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{
@ -367,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;
}
@ -375,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;
}
@ -396,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

@ -16,8 +16,6 @@ import android.util.Log;
import com.felhr.utils.SafeUsbRequest;
import java.util.concurrent.atomic.AtomicBoolean;
public class CH34xSerialDevice extends UsbSerialDevice
{
private static final String CLASS_ID = CH34xSerialDevice.class.getSimpleName();
@ -68,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;
@ -85,7 +89,6 @@ public class CH34xSerialDevice extends UsbSerialDevice
private UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
private FlowControlThread flowControlThread;
private UsbCTSCallback ctsCallback;
@ -118,7 +121,7 @@ public class CH34xSerialDevice extends UsbSerialDevice
if(ret)
{
// Initialize UsbRequest
requestIN = new SafeUsbRequest();
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
@ -253,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!");
}
}
@ -270,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)
{
@ -609,66 +628,48 @@ public class CH34xSerialDevice extends UsbSerialDevice
}
}
private class FlowControlThread extends Thread
private class FlowControlThread extends AbstractWorkerThread
{
private long time = 100; // 100ms
private boolean firstTime;
private AtomicBoolean keep;
public FlowControlThread()
{
keep = new AtomicBoolean(true);
firstTime = true;
}
private final long time = 100; // 100ms
@Override
public void run()
public void doRun()
{
while(keep.get())
if(!firstTime)
{
if(!firstTime)
// Check CTS status
if(rtsCtsEnabled)
{
// Check CTS status
if(rtsCtsEnabled)
boolean cts = pollForCTS();
if(ctsState != cts)
{
boolean cts = pollForCTS();
if(ctsState != cts)
{
ctsState = !ctsState;
if (ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
}
ctsState = !ctsState;
if (ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
}
// Check DSR status
if(dtrDsrEnabled)
{
boolean dsr = pollForDSR();
if(dsrState != dsr)
{
dsrState = !dsrState;
if (dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
}
}
}else
{
if(rtsCtsEnabled && ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
if(dtrDsrEnabled && dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
firstTime = false;
}
}
}
public void stopThread()
{
keep.set(false);
// Check DSR status
if(dtrDsrEnabled)
{
boolean dsr = pollForDSR();
if(dsrState != dsr)
{
dsrState = !dsrState;
if (dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
}
}
}else
{
if(rtsCtsEnabled && ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
if(dtrDsrEnabled && dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
firstTime = false;
}
}
public boolean pollForCTS()

Wyświetl plik

@ -10,16 +10,16 @@ import android.util.Log;
import com.felhr.utils.SafeUsbRequest;
import java.util.concurrent.atomic.AtomicBoolean;
public class CP2102SerialDevice extends UsbSerialDevice
{
private static final String CLASS_ID = CP2102SerialDevice.class.getSimpleName();
private static final int CP210x_PURGE = 0x12;
private static final int CP210x_IFC_ENABLE = 0x00;
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;
@ -32,11 +32,16 @@ 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;
private static final int CP210x_MHS_DTR_OFF = 0x100;
private static final int CP210x_PURGE_ALL = 0x000f;
/***
* Default Serial Configuration
* Baud rate: 9600
@ -67,10 +72,9 @@ public class CP2102SerialDevice extends UsbSerialDevice
private UsbCTSCallback ctsCallback;
private UsbDSRCallback dsrCallback;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
private FlowControlThread flowControlThread;
@ -103,7 +107,7 @@ public class CP2102SerialDevice extends UsbSerialDevice
if(ret)
{
// Initialize UsbRequest
requestIN = new SafeUsbRequest();
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
@ -130,6 +134,7 @@ public class CP2102SerialDevice extends UsbSerialDevice
@Override
public void close()
{
setControlCommand(CP210x_PURGE, CP210x_PURGE_ALL, null);
setControlCommand(CP210x_IFC_ENABLE, CP210x_UART_DISABLE, null);
killWorkingThread();
killWriteThread();
@ -165,6 +170,7 @@ public class CP2102SerialDevice extends UsbSerialDevice
@Override
public void syncClose()
{
setControlCommand(CP210x_PURGE, CP210x_PURGE_ALL, null);
setControlCommand(CP210x_IFC_ENABLE, CP210x_UART_DISABLE, null);
stopFlowControlThread();
connection.releaseInterface(mInterface);
@ -186,94 +192,75 @@ public class CP2102SerialDevice extends UsbSerialDevice
@Override
public void setDataBits(int dataBits)
{
byte[] data = getCTL();
short wValue = getCTL();
wValue &= ~0x0F00;
switch(dataBits)
{
case UsbSerialInterface.DATA_BITS_5:
data[1] = 5;
wValue |= 0x0500;
break;
case UsbSerialInterface.DATA_BITS_6:
data[1] = 6;
wValue |= 0x0600;
break;
case UsbSerialInterface.DATA_BITS_7:
data[1] = 7;
wValue |= 0x0700;
break;
case UsbSerialInterface.DATA_BITS_8:
data[1] = 8;
wValue |= 0x0800;
break;
default:
return;
}
byte wValue = (byte) ((data[1] << 8) | (data[0] & 0xFF));
setControlCommand(CP210x_SET_LINE_CTL, wValue, null);
}
@Override
public void setStopBits(int stopBits)
{
byte[] data = getCTL();
short wValue = getCTL();
wValue &= ~0x0003;
switch(stopBits)
{
case UsbSerialInterface.STOP_BITS_1:
data[0] &= ~1;
data[0] &= ~(1 << 1);
wValue |= 0;
break;
case UsbSerialInterface.STOP_BITS_15:
data[0] |= 1;
data[0] &= ~(1 << 1) ;
wValue |= 1;
break;
case UsbSerialInterface.STOP_BITS_2:
data[0] &= ~1;
data[0] |= (1 << 1);
wValue |= 2;
break;
default:
return;
}
byte wValue = (byte) ((data[1] << 8) | (data[0] & 0xFF));
setControlCommand(CP210x_SET_LINE_CTL, wValue, null);
}
@Override
public void setParity(int parity)
{
byte[] data = getCTL();
short wValue = getCTL();
wValue &= ~0x00F0;
switch(parity)
{
case UsbSerialInterface.PARITY_NONE:
data[0] &= ~(1 << 4);
data[0] &= ~(1 << 5);
data[0] &= ~(1 << 6);
data[0] &= ~(1 << 7);
wValue |= 0x0000;
break;
case UsbSerialInterface.PARITY_ODD:
data[0] |= (1 << 4);
data[0] &= ~(1 << 5);
data[0] &= ~(1 << 6);
data[0] &= ~(1 << 7);
wValue |= 0x0010;
break;
case UsbSerialInterface.PARITY_EVEN:
data[0] &= ~(1 << 4);
data[0] |= (1 << 5);
data[0] &= ~(1 << 6);
data[0] &= ~(1 << 7);
wValue |= 0x0020;
break;
case UsbSerialInterface.PARITY_MARK:
data[0] |= (1 << 4);
data[0] |= (1 << 5);
data[0] &= ~(1 << 6);
data[0] &= ~(1 << 7);
wValue |= 0x0030;
break;
case UsbSerialInterface.PARITY_SPACE:
data[0] &= ~(1 << 4);
data[0] &= ~(1 << 5);
data[0] |= (1 << 6);
data[0] &= ~(1 << 7);
wValue |= 0x0040;
break;
default:
return;
}
byte wValue = (byte) ((data[1] << 8) | (data[0] & 0xFF));
setControlCommand(CP210x_SET_LINE_CTL, wValue, null);
}
@ -343,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)
{
@ -407,106 +404,88 @@ public class CP2102SerialDevice extends UsbSerialDevice
/*
Thread to check every X time if flow signals CTS or DSR have been raised
*/
private class FlowControlThread extends Thread
private class FlowControlThread extends AbstractWorkerThread
{
private long time = 40; // 40ms
private boolean firstTime;
private AtomicBoolean keep;
public FlowControlThread()
{
keep = new AtomicBoolean(true);
firstTime = true;
}
private final long time = 40; // 40ms
@Override
public void run()
public void doRun()
{
while(keep.get())
if(!firstTime) // Only execute the callback when the status change
{
if(!firstTime) // Only execute the callback when the status change
byte[] modemState = pollLines();
byte[] commStatus = getCommStatus();
// Check CTS status
if(rtsCtsEnabled)
{
byte[] modemState = pollLines();
byte[] commStatus = getCommStatus();
// Check CTS status
if(rtsCtsEnabled)
if(ctsState != ((modemState[0] & 0x10) == 0x10))
{
if(ctsState != ((modemState[0] & 0x10) == 0x10))
{
ctsState = !ctsState;
if (ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
}
ctsState = !ctsState;
if (ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
}
// Check DSR status
if(dtrDsrEnabled)
{
if(dsrState != ((modemState[0] & 0x20) == 0x20))
{
dsrState = !dsrState;
if (dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
}
}
//Check Parity Errors
if(parityCallback != null)
{
if((commStatus[0] & 0x10) == 0x10)
{
parityCallback.onParityError();
}
}
// Check frame error
if(frameCallback != null)
{
if((commStatus[0] & 0x02) == 0x02)
{
frameCallback.onFramingError();
}
}
// Check break interrupt
if(breakCallback != null)
{
if((commStatus[0] & 0x01) == 0x01)
{
breakCallback.onBreakInterrupt();
}
}
// Check Overrun error
if(overrunCallback != null)
{
if((commStatus[0] & 0x04) == 0x04
|| (commStatus[0] & 0x8) == 0x08)
{
overrunCallback.onOverrunError();
}
}
}else // Execute the callback always the first time
{
if(rtsCtsEnabled && ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
if(dtrDsrEnabled && dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
firstTime = false;
}
}
}
public void stopThread()
{
keep.set(false);
// Check DSR status
if(dtrDsrEnabled)
{
if(dsrState != ((modemState[0] & 0x20) == 0x20))
{
dsrState = !dsrState;
if (dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
}
}
//Check Parity Errors
if(parityCallback != null)
{
if((commStatus[0] & 0x10) == 0x10)
{
parityCallback.onParityError();
}
}
// Check frame error
if(frameCallback != null)
{
if((commStatus[0] & 0x02) == 0x02)
{
frameCallback.onFramingError();
}
}
// Check break interrupt
if(breakCallback != null)
{
if((commStatus[0] & 0x01) == 0x01)
{
breakCallback.onBreakInterrupt();
}
}
// Check Overrun error
if(overrunCallback != null)
{
if((commStatus[0] & 0x04) == 0x04
|| (commStatus[0] & 0x8) == 0x08)
{
overrunCallback.onOverrunError();
}
}
}else // Execute the callback always the first time
{
if(rtsCtsEnabled && ctsCallback != null)
ctsCallback.onCTSChanged(ctsState);
if(dtrDsrEnabled && dsrCallback != null)
dsrCallback.onDSRChanged(dsrState);
firstTime = false;
}
}
private byte[] pollLines()
@ -613,11 +592,11 @@ public class CP2102SerialDevice extends UsbSerialDevice
return data;
}
private byte[] getCTL()
private short getCTL()
{
byte[] data = new byte[2];
int response = connection.controlTransfer(CP210x_REQTYPE_DEVICE2HOST, CP210x_GET_LINE_CTL, 0, mInterface.getId(), data, data.length, USB_TIMEOUT);
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
return data;
return (short)((data[1] << 8) | (data[0] & 0xFF));
}
}

Wyświetl plik

@ -11,7 +11,7 @@ import android.util.Log;
public class CP2130SpiDevice extends UsbSpiDevice
{
private static String CLASS_ID = CP2130SpiDevice.class.getSimpleName();
private static final String CLASS_ID = CP2130SpiDevice.class.getSimpleName();
public static final int CLOCK_12MHz = 0;
public static final int CLOCK_6MHz = 1;
@ -29,7 +29,7 @@ public class CP2130SpiDevice extends UsbSpiDevice
private static final int SET_GPIO_CHIP_SELECT = 0x25;
private static final int GET_SPI_WORD = 0x30;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;

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;
@ -63,6 +72,7 @@ public class FTDISerialDevice extends UsbSerialDevice
private static final int FTDI_SET_MODEM_CTRL_DEFAULT3 = 0x0100;
private static final int FTDI_SET_MODEM_CTRL_DEFAULT4 = 0x0200;
private static final int FTDI_SET_FLOW_CTRL_DEFAULT = 0x0000;
private static final byte[] EMPTY_BYTE_ARRAY = {};
private int currentSioSetData = 0x0000;
@ -79,10 +89,9 @@ public class FTDISerialDevice extends UsbSerialDevice
private UsbCTSCallback ctsCallback;
private UsbDSRCallback dsrCallback;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
public FTDIUtilities ftdiUtilities;
@ -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);
@ -117,7 +125,7 @@ public class FTDISerialDevice extends UsbSerialDevice
if(ret)
{
// Initialize UsbRequest
requestIN = new SafeUsbRequest();
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
@ -141,8 +149,8 @@ public class FTDISerialDevice extends UsbSerialDevice
@Override
public void close()
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0);
currentSioSetData = 0x0000;
killWorkingThread();
killWriteThread();
@ -176,8 +184,8 @@ public class FTDISerialDevice extends UsbSerialDevice
@Override
public void syncClose()
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT3, 0);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT4, 0);
currentSioSetData = 0x0000;
connection.releaseInterface(mInterface);
isOpen = false;
@ -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, null);
short[] encodedBaudRate = encodedBaudRate(baudRate);
if(encodedBaudRate != null) {
setEncodedBaudRate(encodedBaudRate);
}else{
setOldBaudRate(baudRate);
}
}
@Override
@ -230,35 +213,35 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.DATA_BITS_6:
currentSioSetData &= ~1;
currentSioSetData |= (1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.DATA_BITS_7:
currentSioSetData |= 1;
currentSioSetData |= (1 << 1);
currentSioSetData |= (1 << 2);
currentSioSetData &= ~(1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.DATA_BITS_8:
currentSioSetData &= ~1;
currentSioSetData &= ~(1 << 1);
currentSioSetData &= ~(1 << 2);
currentSioSetData |= (1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~1;
currentSioSetData &= ~(1 << 1);
currentSioSetData &= ~(1 << 2);
currentSioSetData |= (1 << 3);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
}
@ -273,25 +256,25 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.STOP_BITS_15:
currentSioSetData |= (1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.STOP_BITS_2:
currentSioSetData &= ~(1 << 11);
currentSioSetData |= (1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~(1 << 11);
currentSioSetData &= ~(1 << 12);
currentSioSetData &= ~(1 << 13);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
}
}
@ -305,37 +288,37 @@ public class FTDISerialDevice extends UsbSerialDevice
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_ODD:
currentSioSetData |= (1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_EVEN:
currentSioSetData &= ~(1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_MARK:
currentSioSetData |= (1 << 8);
currentSioSetData |= (1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
case UsbSerialInterface.PARITY_SPACE:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData |= (1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
default:
currentSioSetData &= ~(1 << 8);
currentSioSetData &= ~(1 << 9);
currentSioSetData &= ~(1 << 10);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0, null);
setControlCommand(FTDI_SIO_SET_DATA, currentSioSetData, 0);
break;
}
@ -347,7 +330,7 @@ public class FTDISerialDevice extends UsbSerialDevice
switch(flowControl)
{
case UsbSerialInterface.FLOW_CONTROL_OFF:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0);
rtsCtsEnabled = false;
dtrDsrEnabled = false;
break;
@ -355,34 +338,49 @@ public class FTDISerialDevice extends UsbSerialDevice
rtsCtsEnabled = true;
dtrDsrEnabled = false;
int indexRTSCTS = 0x0001;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexRTSCTS, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexRTSCTS);
break;
case UsbSerialInterface.FLOW_CONTROL_DSR_DTR:
dtrDsrEnabled = true;
rtsCtsEnabled = false;
int indexDSRDTR = 0x0002;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexDSRDTR , null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, indexDSRDTR);
break;
case UsbSerialInterface.FLOW_CONTROL_XON_XOFF:
int indexXONXOFF = 0x0004;
int wValue = 0x1311;
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, wValue, indexXONXOFF , null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, wValue, indexXONXOFF);
break;
default:
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null);
setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0);
break;
}
}
/**
* 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)
{
if(state)
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_HIGH, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_HIGH, 0);
}else
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_LOW, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_RTS_LOW, 0);
}
}
@ -391,10 +389,10 @@ public class FTDISerialDevice extends UsbSerialDevice
{
if(state)
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_HIGH, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_HIGH, 0);
}else
{
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_LOW, 0, null);
setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SIO_SET_DTR_LOW, 0);
}
}
@ -462,18 +460,18 @@ public class FTDISerialDevice extends UsbSerialDevice
// Default Setup
firstTime = true;
if(setControlCommand(FTDI_SIO_RESET, 0x00, 0, null) < 0)
if(setControlCommand(FTDI_SIO_RESET, 0x00, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_DATA, FTDI_SET_DATA_DEFAULT, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_DATA, FTDI_SET_DATA_DEFAULT, 0) < 0)
return false;
currentSioSetData = FTDI_SET_DATA_DEFAULT;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT1, 0, null) < 0)
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT1, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT2, 0, null) < 0)
if(setControlCommand(FTDI_SIO_MODEM_CTRL, FTDI_SET_MODEM_CTRL_DEFAULT2, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_FLOW_CTRL, FTDI_SET_FLOW_CTRL_DEFAULT, 0) < 0)
return false;
if(setControlCommand(FTDI_SIO_SET_BAUD_RATE, FTDI_BAUDRATE_9600, 0, null) < 0)
if(setControlCommand(FTDI_SIO_SET_BAUD_RATE, FTDI_BAUDRATE_9600, 0) < 0)
return false;
// Flow control disabled by default
@ -483,18 +481,60 @@ public class FTDISerialDevice extends UsbSerialDevice
return true;
}
private int setControlCommand(int request, int value, int index, byte[] data)
private int setControlCommand(int request, int value, int index)
{
int dataLength = 0;
if(data != null)
{
dataLength = data.length;
}
int response = connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, request, value, mInterface.getId() + 1 + index, data, dataLength, USB_TIMEOUT);
int response = connection.controlTransfer(FTDI_REQTYPE_HOST2DEVICE, request, value, mInterface.getId() + 1 + index, null, dataLength, USB_TIMEOUT);
Log.i(CLASS_ID,"Control Transfer Response: " + String.valueOf(response));
return response;
}
// Special treatment needed to FTDI devices
static 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 if (length == 2) // special case optimization that returns the same instance.
{
return EMPTY_BYTE_ARRAY;
}
else
{
return Arrays.copyOfRange(ftdiData, 2, length);
}
}
// Copy data without FTDI headers
private static void copyData(byte[] src, byte[] dst)
{
int srcPos = 2, dstPos = 0;
while(srcPos - 2 <= src.length - 64)
{
System.arraycopy(src, srcPos, dst, dstPos, 62);
srcPos += 64;
dstPos += 62;
}
int remaining = src.length - srcPos + 2;
if (remaining > 0)
{
System.arraycopy(src, srcPos, dst, dstPos, remaining - 2);
}
}
public class FTDIUtilities
{
// Special treatment needed to FTDI devices
@ -590,31 +630,6 @@ public class FTDISerialDevice extends UsbSerialDevice
}
}
}
// Copy data without FTDI headers
private void copyData(byte[] src, byte[] dst)
{
int i = 0; // src index
int j = 0; // dst index
while(i <= src.length-1)
{
if(i != 0 && i != 1)
{
if(i % 64 == 0 && i >= 64)
{
i += 2;
}else
{
dst[j] = src[i];
i++;
j++;
}
}else
{
i++;
}
}
}
}
@Override
@ -673,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

@ -22,7 +22,7 @@ public class PL2303SerialDevice extends UsbSerialDevice
private static final int PL2303_SET_LINE_CODING = 0x20;
private static final int PL2303_SET_CONTROL_REQUEST = 0x22;
private byte[] defaultSetLine = new byte[]{
private final byte[] defaultSetLine = new byte[]{
(byte) 0x80, // [0:3] Baud rate (reverse hex encoding 9600:00 00 25 80 -> 80 25 00 00)
(byte) 0x25,
(byte) 0x00,
@ -33,10 +33,9 @@ public class PL2303SerialDevice extends UsbSerialDevice
};
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
public PL2303SerialDevice(UsbDevice device, UsbDeviceConnection connection)
@ -64,7 +63,7 @@ public class PL2303SerialDevice extends UsbSerialDevice
if(ret)
{
// Initialize UsbRequest
requestIN = new SafeUsbRequest();
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
@ -265,6 +264,12 @@ public class PL2303SerialDevice extends UsbSerialDevice
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -1,16 +1,19 @@
package com.felhr.usbserial;
import java.nio.BufferOverflowException;
import java.io.EOFException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import okio.Buffer;
public class SerialBuffer
{
public static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
public static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024;
static final int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
static final int MAX_BULK_BUFFER = 16 * 1024;
private ByteBuffer readBuffer;
private SynchronizedBuffer writeBuffer;
private byte[] readBuffer_compatible; // Read buffer for android < 4.2
private final SynchronizedBuffer writeBuffer;
private byte[] readBufferCompatible; // Read buffer for android < 4.2
private boolean debugging = false;
public SerialBuffer(boolean version)
@ -22,7 +25,7 @@ public class SerialBuffer
}else
{
readBuffer_compatible = new byte[DEFAULT_READ_BUFFER_SIZE];
readBufferCompatible = new byte[DEFAULT_READ_BUFFER_SIZE];
}
}
@ -34,20 +37,6 @@ public class SerialBuffer
debugging = value;
}
public void putReadBuffer(ByteBuffer data)
{
synchronized(this)
{
try
{
readBuffer.put(data);
}catch(BufferOverflowException e)
{
// TO-DO
}
}
}
public ByteBuffer getReadBuffer()
{
synchronized(this)
@ -89,57 +78,39 @@ public class SerialBuffer
}
public void resetWriteBuffer()
{
writeBuffer.reset();
}
public byte[] getBufferCompatible()
{
return readBuffer_compatible;
return readBufferCompatible;
}
public byte[] getDataReceivedCompatible(int numberBytes)
{
byte[] tempBuff = Arrays.copyOfRange(readBuffer_compatible, 0, numberBytes);
return tempBuff;
return Arrays.copyOfRange(readBufferCompatible, 0, numberBytes);
}
private class SynchronizedBuffer
{
private byte[] buffer;
private int position;
private final Buffer buffer;
public SynchronizedBuffer()
SynchronizedBuffer()
{
this.buffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
position = -1;
this.buffer = new Buffer();
}
public synchronized void put(byte[] src)
synchronized void put(byte[] src)
{
if(src == null || src.length == 0) return;
if(position == -1)
position = 0;
if(debugging)
UsbSerialDebugger.printLogPut(src, true);
if(position + src.length > DEFAULT_WRITE_BUFFER_SIZE - 1) //Checking bounds. Source data does not fit in buffer
{
if(position < DEFAULT_WRITE_BUFFER_SIZE)
System.arraycopy(src, 0, buffer, position, DEFAULT_WRITE_BUFFER_SIZE - position);
position = DEFAULT_WRITE_BUFFER_SIZE;
notify();
}else // Source data fits in buffer
{
System.arraycopy(src, 0, buffer, position, src.length);
position += src.length;
notify();
}
buffer.write(src);
notify();
}
public synchronized byte[] get()
synchronized byte[] get()
{
if(position == -1)
if(buffer.size() == 0)
{
try
{
@ -147,19 +118,25 @@ public class SerialBuffer
} catch (InterruptedException e)
{
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
if(position <= -1 ) return new byte[0];
byte[] dst = Arrays.copyOfRange(buffer, 0, position);
byte[] dst;
if(buffer.size() <= MAX_BULK_BUFFER){
dst = buffer.readByteArray();
}else{
try {
dst = buffer.readByteArray(MAX_BULK_BUFFER);
} catch (EOFException e) {
e.printStackTrace();
return new byte[0];
}
}
if(debugging)
UsbSerialDebugger.printLogGet(dst, true);
position = -1;
return dst;
}
public synchronized void reset()
{
position = -1;
return dst;
}
}

Wyświetl plik

@ -9,7 +9,7 @@ public class SerialInputStream extends InputStream
private int maxBufferSize = 16 * 1024;
private byte[] buffer;
private final byte[] buffer;
private int pointer;
private int bufferSize;
@ -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

@ -18,7 +18,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
public class SerialPortBuilder {
private static final String ACTION_USB_PERMISSION = "com.felhr.usbserial.USB_PERMISSION";
@ -30,14 +29,12 @@ public class SerialPortBuilder {
private List<UsbDeviceStatus> devices;
private List<UsbSerialDevice> serialDevices = new ArrayList<>();
private ArrayBlockingQueue<PendingUsbPermission> queuedPermissions = new ArrayBlockingQueue<>(100);
private AtomicBoolean processingPermission = new AtomicBoolean(false);
private final ArrayBlockingQueue<PendingUsbPermission> queuedPermissions = new ArrayBlockingQueue<>(100);
private volatile boolean processingPermission = false;
private PendingUsbPermission currentPendingPermission;
private UsbManager usbManager;
private SerialPortCallback serialPortCallback;
private InitSerialPortThread initSerialPortThread;
private final SerialPortCallback serialPortCallback;
private int baudRate, dataBits, stopBits, parity, flowControl;
private int mode = 0;
@ -87,7 +84,7 @@ public class SerialPortBuilder {
queuedPermissions.add(createUsbPermission(context, deviceStatus));
}
if(!processingPermission.get()){
if(!processingPermission){
launchPermission();
}
@ -107,7 +104,7 @@ public class SerialPortBuilder {
devices.addAll(newDevices);
if(!processingPermission.get()){
if(!processingPermission){
launchPermission();
}
}
@ -133,17 +130,18 @@ public class SerialPortBuilder {
}
public boolean disconnectDevice(UsbDevice usbDevice){
Optional<UsbSerialDevice> optionalDevice = Stream.of(serialDevices)
List<UsbSerialDevice> devices = Stream.of(serialDevices)
.filter(p -> usbDevice.getDeviceId() == p.getDeviceId())
.findSingle();
.toList();
if(optionalDevice.isPresent()){
UsbSerialDevice disconnectedDevice = optionalDevice.get();
disconnectedDevice.syncClose();
int removedDevices = 0;
for(UsbSerialDevice device : devices){
device.syncClose();
serialDevices = Utils.removeIf(serialDevices, p -> usbDevice.getDeviceId() == p.getDeviceId());
return true;
removedDevices ++;
}
return false;
return removedDevices == devices.size();
}
public void unregisterListeners(Context context){
@ -164,13 +162,13 @@ public class SerialPortBuilder {
private void launchPermission(){
try {
processingPermission.set(true);
processingPermission = true;
currentPendingPermission = queuedPermissions.take();
usbManager.requestPermission(currentPendingPermission.usbDeviceStatus.usbDevice,
currentPendingPermission.pendingIntent);
} catch (InterruptedException e) {
e.printStackTrace();
processingPermission.set(false);
processingPermission = false;
}
}
@ -204,12 +202,13 @@ public class SerialPortBuilder {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
InitSerialPortThread initSerialPortThread;
if (granted) {
createAllPorts(currentPendingPermission.usbDeviceStatus);
if(queuedPermissions.size() > 0) {
launchPermission();
}else{
processingPermission.set(false);
processingPermission = false;
if(mode == MODE_START) {
serialPortCallback.onSerialPortsDetected(serialDevices);
}else{
@ -221,7 +220,7 @@ public class SerialPortBuilder {
if(queuedPermissions.size() > 0) {
launchPermission();
}else{
processingPermission.set(false);
processingPermission = false;
if(mode == MODE_START) {
serialPortCallback.onSerialPortsDetected(serialDevices);
}else{
@ -236,7 +235,7 @@ public class SerialPortBuilder {
private class InitSerialPortThread extends Thread {
private List<UsbSerialDevice> usbSerialDevices;
private final List<UsbSerialDevice> usbSerialDevices;
public InitSerialPortThread(List<UsbSerialDevice> usbSerialDevices) {
this.usbSerialDevices = usbSerialDevices;

Wyświetl plik

@ -1,12 +1,11 @@
package com.felhr.usbserial;
import java.util.concurrent.atomic.AtomicBoolean;
import com.felhr.deviceids.CH34xIds;
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,14 +21,15 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
public static final String FTDI = "ftdi";
public static final String PL2303 = "pl2303";
private static final String CLASS_ID = UsbSerialDevice.class.getSimpleName();
protected static final String COM_PORT = "COM ";
private static 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;
protected static final int USB_TIMEOUT = 5000;
protected static final int USB_TIMEOUT = 0;
protected SerialBuffer serialBuffer;
@ -50,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;
@ -82,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);
@ -117,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;
@ -226,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);
@ -237,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)
@ -304,52 +326,47 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
/*
* WorkerThread waits for request notifications from IN endpoint
*/
protected class WorkerThread extends Thread
protected class WorkerThread extends AbstractWorkerThread
{
private UsbSerialDevice usbSerialDevice;
private final UsbSerialDevice usbSerialDevice;
private UsbReadCallback callback;
private UsbRequest requestIN;
private AtomicBoolean working;
public WorkerThread(UsbSerialDevice usbSerialDevice)
{
this.usbSerialDevice = usbSerialDevice;
working = new AtomicBoolean(true);
}
@Override
public void run()
public void doRun()
{
while(working.get())
UsbRequest request = connection.requestWait();
if(request != null && request.getEndpoint().getType() == UsbConstants.USB_ENDPOINT_XFER_BULK
&& request.getEndpoint().getDirection() == UsbConstants.USB_DIR_IN)
{
UsbRequest request = connection.requestWait();
if(request != null && request.getEndpoint().getType() == UsbConstants.USB_ENDPOINT_XFER_BULK
&& request.getEndpoint().getDirection() == UsbConstants.USB_DIR_IN)
byte[] data = serialBuffer.getDataReceived();
// FTDI devices reserves two first bytes of an IN endpoint with info about
// modem and Line.
if(isFTDIDevice())
{
byte[] data = serialBuffer.getDataReceived();
((FTDISerialDevice) usbSerialDevice).ftdiUtilities.checkModemStatus(data); //Check the Modem status
serialBuffer.clearReadBuffer();
// FTDI devices reserves two first bytes of an IN endpoint with info about
// modem and Line.
if(isFTDIDevice())
if(data.length > 2)
{
((FTDISerialDevice) usbSerialDevice).ftdiUtilities.checkModemStatus(data); //Check the Modem status
serialBuffer.clearReadBuffer();
if(data.length > 2)
{
data = ((FTDISerialDevice) usbSerialDevice).ftdiUtilities.adaptArray(data);
onReceivedData(data);
}
}else
{
// Clear buffer, execute the callback
serialBuffer.clearReadBuffer();
data = FTDISerialDevice.adaptArray(data);
onReceivedData(data);
}
// Queue a new request
requestIN.queue(serialBuffer.getReadBuffer(), SerialBuffer.DEFAULT_READ_BUFFER_SIZE);
}else
{
// Clear buffer, execute the callback
serialBuffer.clearReadBuffer();
onReceivedData(data);
}
// Queue a new request
requestIN.queue(serialBuffer.getReadBuffer(), SerialBuffer.DEFAULT_READ_BUFFER_SIZE);
}
}
@ -373,57 +390,36 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
if(callback != null)
callback.onReceivedData(data);
}
public void stopWorkingThread()
{
working.set(false);
}
}
protected class WriteThread extends Thread
private class WriteThread extends AbstractWorkerThread
{
private UsbEndpoint outEndpoint;
private AtomicBoolean working;
public WriteThread()
{
working = new AtomicBoolean(true);
}
@Override
public void run()
public void doRun()
{
while(working.get())
{
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
public void setUsbEndpoint(UsbEndpoint outEndpoint)
{
this.outEndpoint = outEndpoint;
}
public void stopWriteThread()
{
working.set(false);
}
}
protected class ReadThread extends Thread
protected class ReadThread extends AbstractWorkerThread
{
private UsbSerialDevice usbSerialDevice;
private final UsbSerialDevice usbSerialDevice;
private UsbReadCallback callback;
private UsbEndpoint inEndpoint;
private AtomicBoolean working;
public ReadThread(UsbSerialDevice usbSerialDevice)
{
this.usbSerialDevice = usbSerialDevice;
working = new AtomicBoolean(true);
}
public void setCallback(UsbReadCallback callback)
@ -432,38 +428,34 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
}
@Override
public void run()
public void doRun()
{
byte[] dataReceived = null;
int numberBytes;
if(inEndpoint != null)
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 0);
else
numberBytes = 0;
while(working.get())
if(numberBytes > 0)
{
int numberBytes;
if(inEndpoint != null)
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 0);
else
numberBytes = 0;
dataReceived = serialBuffer.getDataReceivedCompatible(numberBytes);
if(numberBytes > 0)
// FTDI devices reserve two first bytes of an IN endpoint with info about
// modem and Line.
if(isFTDIDevice())
{
dataReceived = serialBuffer.getDataReceivedCompatible(numberBytes);
((FTDISerialDevice) usbSerialDevice).ftdiUtilities.checkModemStatus(dataReceived);
// FTDI devices reserve two first bytes of an IN endpoint with info about
// modem and Line.
if(isFTDIDevice())
{
((FTDISerialDevice) usbSerialDevice).ftdiUtilities.checkModemStatus(dataReceived);
if(dataReceived.length > 2)
{
dataReceived = ((FTDISerialDevice) usbSerialDevice).ftdiUtilities.adaptArray(dataReceived);
onReceivedData(dataReceived);
}
}else
if(dataReceived.length > 2)
{
dataReceived = FTDISerialDevice.adaptArray(dataReceived);
onReceivedData(dataReceived);
}
}else
{
onReceivedData(dataReceived);
}
}
}
@ -473,11 +465,6 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
this.inEndpoint = inEndpoint;
}
public void stopReadThread()
{
working.set(false);
}
private void onReceivedData(byte[] data)
{
if(callback != null)
@ -493,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);
}
}
@ -511,11 +497,11 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
{
if(mr1Version && workerThread != null)
{
workerThread.stopWorkingThread();
workerThread.stopThread();
workerThread = null;
}else if(!mr1Version && readThread != null)
{
readThread.stopReadThread();
readThread.stopThread();
readThread = null;
}
}
@ -542,9 +528,8 @@ public abstract class UsbSerialDevice implements UsbSerialInterface
{
if(writeThread != null)
{
writeThread.stopWriteThread();
writeThread.stopThread();
writeThread = null;
serialBuffer.resetWriteBuffer();
}
}

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

@ -6,11 +6,8 @@ import android.hardware.usb.UsbEndpoint;
import com.felhr.deviceids.CP2130Ids;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class UsbSpiDevice implements UsbSpiInterface
{
private static final String CLASS_ID = UsbSerialDevice.class.getSimpleName();
protected static final int USB_TIMEOUT = 5000;
@ -83,48 +80,28 @@ public abstract class UsbSpiDevice implements UsbSpiInterface
@Override
public abstract void closeSPI();
protected class WriteThread extends Thread
protected class WriteThread extends AbstractWorkerThread
{
private UsbEndpoint outEndpoint;
private AtomicBoolean working;
public WriteThread()
{
working = new AtomicBoolean(true);
}
@Override
public void run()
public void doRun()
{
while(working.get())
{
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
byte[] data = serialBuffer.getWriteBuffer();
if(data.length > 0)
connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
}
public void setUsbEndpoint(UsbEndpoint outEndpoint)
{
this.outEndpoint = outEndpoint;
}
public void stopWriteThread()
{
working.set(false);
}
}
protected class ReadThread extends Thread
protected class ReadThread extends AbstractWorkerThread
{
private UsbMISOCallback misoCallback;
private UsbEndpoint inEndpoint;
private AtomicBoolean working;
public ReadThread()
{
working = new AtomicBoolean(true);
}
public void setCallback(UsbMISOCallback misoCallback)
{
@ -132,26 +109,22 @@ public abstract class UsbSpiDevice implements UsbSpiInterface
}
@Override
public void run()
public void doRun()
{
byte[] dataReceived = null;
int numberBytes;
if(inEndpoint != null)
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 0);
else
numberBytes = 0;
while(working.get())
if(numberBytes > 0)
{
int numberBytes;
if(inEndpoint != null)
numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 0);
else
numberBytes = 0;
if(numberBytes > 0)
{
dataReceived = serialBuffer.getDataReceivedCompatible(numberBytes);
onReceivedData(dataReceived);
}
dataReceived = serialBuffer.getDataReceivedCompatible(numberBytes);
onReceivedData(dataReceived);
}
}
public void setUsbEndpoint(UsbEndpoint inEndpoint)
@ -159,11 +132,6 @@ public abstract class UsbSpiDevice implements UsbSpiInterface
this.inEndpoint = inEndpoint;
}
public void stopReadThread()
{
working.set(false);
}
private void onReceivedData(byte[] data)
{
if(misoCallback != null)
@ -187,7 +155,7 @@ public abstract class UsbSpiDevice implements UsbSpiInterface
{
if(readThread != null)
{
readThread.stopReadThread();
readThread.stopThread();
readThread = null;
}
}
@ -206,9 +174,8 @@ public abstract class UsbSpiDevice implements UsbSpiInterface
{
if(writeThread != null)
{
writeThread.stopWriteThread();
writeThread.stopThread();
writeThread = null;
serialBuffer.resetWriteBuffer();
}
}

Wyświetl plik

@ -49,10 +49,9 @@ public class XdcVcpSerialDevice extends UsbSerialDevice
private static final int XDCVCP_XOFF = 0x0000;
private static final int DEFAULT_BAUDRATE = 115200;
private UsbInterface mInterface;
private final UsbInterface mInterface;
private UsbEndpoint inEndpoint;
private UsbEndpoint outEndpoint;
private UsbRequest requestIN;
public XdcVcpSerialDevice(UsbDevice device, UsbDeviceConnection connection)
{
@ -110,7 +109,7 @@ public class XdcVcpSerialDevice extends UsbSerialDevice
return false;
// Initialize UsbRequest
requestIN = new UsbRequest();
UsbRequest requestIN = new UsbRequest();
requestIN.initialize(connection, inEndpoint);
// Pass references to the threads
@ -298,6 +297,12 @@ public class XdcVcpSerialDevice extends UsbSerialDevice
}
}
@Override
public void setBreak(boolean state)
{
//TODO
}
@Override
public void setRTS(boolean state)
{

Wyświetl plik

@ -0,0 +1,157 @@
package com.felhr.utils;
import com.annimon.stream.IntStream;
import com.annimon.stream.function.IntPredicate;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// Thanks to Thomas Moorhead for improvements and suggestions
public class ProtocolBuffer {
public static final String BINARY = "binary";
public static final String TEXT = "text";
private String mode;
private static final int DEFAULT_BUFFER_SIZE = 16 * 1024;
private byte[] rawBuffer;
private int bufferPointer = 0;
private byte[] separator;
private String delimiter;
private StringBuilder stringBuffer;
private List<String> commands = new ArrayList<>();
private List<byte[]> rawCommands = new ArrayList<>();
public ProtocolBuffer(String mode){
this.mode = mode;
if(mode.equals(BINARY)){
rawBuffer = new byte[DEFAULT_BUFFER_SIZE];
}else{
stringBuffer = new StringBuilder(DEFAULT_BUFFER_SIZE);
}
}
public ProtocolBuffer(String mode, int bufferSize){
this.mode = mode;
if(mode.equals(BINARY)){
rawBuffer = new byte[bufferSize];
}else{
stringBuffer = new StringBuilder(bufferSize);
}
}
public void setDelimiter(String delimiter){
this.delimiter = delimiter;
}
public void setDelimiter(byte[] delimiter){
this.separator = delimiter;
}
public synchronized void appendData(byte[] data){
// Ignore the frequent empty calls
if (data.length == 0) return;
if(mode.equals(TEXT)){
try {
String dataStr = new String(data, "UTF-8");
stringBuffer.append(dataStr);
String buffer = stringBuffer.toString();
int prevIndex = 0;
int index = buffer.indexOf(delimiter);
while (index >= 0) {
String tempStr = buffer.substring(prevIndex, index + delimiter.length());
commands.add(tempStr);
prevIndex = index + delimiter.length();
index = stringBuffer.toString().indexOf(delimiter, prevIndex);
}
if( /*prevIndex < buffer.length() &&*/ prevIndex > 0){
String tempStr = buffer.substring(prevIndex, buffer.length());
stringBuffer.setLength(0);
stringBuffer.append(tempStr);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}else if(mode.equals(BINARY)){
appendRawData(data);
}
}
public boolean hasMoreCommands(){
if(mode.equals(TEXT)) {
return commands.size() > 0;
}else {
return rawCommands.size() > 0;
}
}
public String nextTextCommand(){
if(commands.size() > 0){
return commands.remove(0);
}else{
return null;
}
}
public byte[] nextBinaryCommand(){
if(rawCommands.size() > 0){
return rawCommands.remove(0);
}else{
return null;
}
}
private void appendRawData(byte[] rawData){
System.arraycopy(rawData, 0, rawBuffer, bufferPointer, rawData.length);
bufferPointer += rawData.length;
SeparatorPredicate predicate = new SeparatorPredicate();
int[] indexes =
IntStream.range(0, bufferPointer)
.filter(predicate)
.toArray();
int prevIndex = 0;
for(Integer i : indexes){
byte[] command = Arrays.copyOfRange(rawBuffer, prevIndex, i + separator.length);
rawCommands.add(command);
prevIndex = i + separator.length;
}
if(prevIndex < rawBuffer.length
&& prevIndex > 0){
byte[] tempBuffer = Arrays.copyOfRange(rawBuffer, prevIndex, rawBuffer.length);
bufferPointer = 0;
System.arraycopy(tempBuffer, 0, rawBuffer, bufferPointer, rawData.length);
bufferPointer += rawData.length;
}
}
private class SeparatorPredicate implements IntPredicate{
@Override
public boolean test(int value) {
if(rawBuffer[value] == separator[0]){
for(int i=1;i<=separator.length-1;i++){
if(rawBuffer[value + i] != separator[i]){
return false;
}
}
return true;
}
return false;
}
}
}

Wyświetl plik

@ -0,0 +1,64 @@
package com.felhr.deviceids;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class DeviceIdTest {
@Test
public void testLongPacking() {
TestCase[] cases = {
new TestCase(0x08FD, 0x000A),
new TestCase(0x0BED, 0x1100),
new TestCase(0x0BED, 0x1101),
new TestCase(0x0FCF, 0x1003),
new TestCase(0x0FCF, 0x1004),
new TestCase(0x0FCF, 0x1006),
new TestCase(0x0FDE, 0xCA05),
new TestCase(0x10A6, 0xAA26),
new TestCase(0x10AB, 0x10C5),
new TestCase(0x10B5, 0xAC70),
new TestCase(0x10C4, 0x0F91),
new TestCase(0x10C4, 0x1101),
new TestCase(0x10C4, 0x1601),
new TestCase(0x10C4, 0x800A),
new TestCase(0x10C4, 0x803B),
new TestCase(0x10C4, 0x8044),
new TestCase(0x10C4, 0x804E),
new TestCase(0x10C4, 0x8053),
new TestCase(0x10C4, 0x8054),
new TestCase(0x10C4, 0x8066),
new TestCase(0x10C4, 0x806F),
new TestCase(0x10C4, 0x807A),
new TestCase(0x10C4, 0x80C4),
new TestCase(0x10C4, 0x80CA),
new TestCase(0x10C4, 0x80DD),
new TestCase(0x10C4, 0x80F6),
new TestCase(0x10C4, 0x8115),
new TestCase(0x10C4, 0x813D),
new TestCase(0x10C4, 0x813F),
new TestCase(0x10C4, 0x814A),
new TestCase(0x10C4, 0x814B),
new TestCase(0x2405, 0x0003),
new TestCase(0x10C4, 0x8156)
};
for (TestCase tc : cases) {
Assert.assertTrue(CP210xIds.isDeviceSupported(tc.vendor, tc.product));
Assert.assertFalse(FTDISioIds.isDeviceIdSupported(tc.vendor, tc.product));
}
}
class TestCase {
final int vendor, product;
TestCase(int vendor, int product) {
this.vendor = vendor;
this.product = product;
}
}
}

Wyświetl plik

@ -0,0 +1,49 @@
package com.felhr.usbserial;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.Arrays;
@RunWith(JUnit4.class)
public class FTDISerialDeviceTest {
@Test
public void adaptEmptyByteArray() {
byte[] onlyHeaders = {1, 2};
byte[] adapted = FTDISerialDevice.adaptArray(onlyHeaders);
Assert.assertEquals("Should be empty", 0, adapted.length);
byte[] adaptAgain = FTDISerialDevice.adaptArray(onlyHeaders);
Assert.assertSame("Should be the same instance of empty array", adapted, adaptAgain);
}
@Test
public void withHeaders() {
byte[] withHeaders = {1, 2, 3, 4, 5, 6};
byte[] wanted = {3,4,5,6};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void fullWithHeaders() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
byte[] wanted = Arrays.copyOfRange(withHeaders, 2, 64);
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void testMultipleFull() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
byte[] wanted = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
@Test
public void testMultiplePartial() {
byte[] withHeaders = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62};
byte[] wanted = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62};
Assert.assertArrayEquals(wanted, FTDISerialDevice.adaptArray(withHeaders));
}
}