Porównaj commity
132 Commity
Autor | SHA1 | Data |
---|---|---|
green-green-avk | 7ad6c9f688 | |
green-green-avk | 9b915b2f84 | |
green-green-avk | 7fe4ce6e50 | |
alex | 94838280cd | |
green-green-avk | 7fff8b6d5c | |
green-green-avk | 4353bf1f4f | |
alex | f0dda6635c | |
green-green-avk | f537d13ede | |
green-green-avk | 3e0fe32f16 | |
Rob Riggs | 6987b48e14 | |
Felipe Herranz | 319cb9de68 | |
Changwoo Ryu | 37eac8d477 | |
Felipe Herranz | 828809f874 | |
Felipe Herranz | 08ef5bbb3f | |
Felipe Herranz | 85c69b540d | |
Felipe Herranz | b967da3c54 | |
Mickael Storck | f4889f03cb | |
Felipe Herranz | d0232ed59a | |
Felipe Herranz | 538e2e0483 | |
Felipe Herranz | 90396ab436 | |
Felipe Herranz | fdfb9f1053 | |
Felipe Herranz | 1e68f744c5 | |
Felipe Herranz | 58bc4a47c3 | |
Felipe Herranz | f0898c3c1d | |
Felipe Herranz | 2f4a4de99c | |
Felipe Herranz | 10d1088228 | |
Felipe Herranz | 4e74b05689 | |
Felipe Herranz | e9eb771541 | |
Felipe Herranz | 9f32a3b7e9 | |
Sven Van Asbroeck | 6180eb497c | |
Charles Julian Knight | f52c67a134 | |
Felipe Herranz | 91a5368445 | |
Felipe Herranz | ffe964f672 | |
Felipe Herranz | 8261ea855c | |
jani | c0c5a2848c | |
Felipe Herranz | 3465c5041e | |
Felipe Herranz | 1823f2b167 | |
Felipe Herranz | 1e672fcb96 | |
Felipe Herranz | bef34df377 | |
xiongyi | 33fed5e09c | |
Felipe Herranz | b6aef50017 | |
Felipe Herranz | 217d651f68 | |
Felipe Herranz | f07bb50b28 | |
Felipe Herranz | ca5379f9c4 | |
Felipe Herranz | 5eddda99e9 | |
Felipe Herranz | 41ced7c2a7 | |
Felipe Herranz | 2afa82ddc3 | |
Felipe Herranz | 8a0d9c8850 | |
Felipe Herranz | 9c51f4c19b | |
Felipe Herranz | 4108a6905e | |
Felipe Herranz | ac88abca1a | |
sonbuidev | 001e745a4a | |
phuongnam0907 | 5ec307966a | |
Felipe Herranz | 3e889f646f | |
Felipe Herranz | 9458b7f136 | |
Felipe Herranz | dcc5063197 | |
Felipe Herranz | 566c20f2b3 | |
Felipe Herranz | aad56b768b | |
Felipe Herranz | da875752b1 | |
Felipe Herranz | 1d7d0d9625 | |
Felipe Herranz | 324ec77db6 | |
Felipe Herranz | 1e4bd132cc | |
Felipe Herranz | 2487b609c5 | |
Raul Bache | b5f7699a52 | |
Felipe Herranz | d369c0d31d | |
Felipe Herranz | b5dd43e5d2 | |
Felipe Herranz | 47f606396c | |
Felipe Herranz | bd350b618e | |
Felipe Herranz | 121598728b | |
Felipe Herranz | 203a65eb54 | |
Raul Bache | b98ea3278d | |
Felipe Herranz | f30817c30f | |
Felipe Herranz | ed8cf6208e | |
Felipe Herranz | d9b790f611 | |
Felipe Herranz | 7ae5df917f | |
Felipe Herranz | 901590bd2e | |
Felipe Herranz | 1e6b5d3938 | |
Felipe Herranz | 050ffb8730 | |
Felipe Herranz | 234c83dd28 | |
Felipe Herranz | 62502d5f1a | |
Felipe Herranz | af18d10953 | |
Raul Bache | b0f2fd2543 | |
Arneball | aeb1227fa2 | |
Raul Bache | d874292505 | |
Felipe Herranz | 37e5dfccd7 | |
Felipe Herranz | 0593683585 | |
Felipe Herranz | aec9b117bc | |
Felipe Herranz | 1751188bd2 | |
Felipe Herranz | 04db5825c0 | |
Felipe Herranz | dc94ea5879 | |
Felipe Herranz | 9d801e780b | |
Felipe Herranz | 3bce693b8d | |
Felipe Herranz | b5863e22cb | |
Felipe Herranz | d02adc6b08 | |
Pawit Pornkitprasan | f25cc0ab7b | |
Felipe Herranz | ab242bd7b3 | |
Felipe Herranz | bb69f4090a | |
Felipe Herranz | 7db4e625d3 | |
Felipe Herranz | 1030409eb2 | |
Felipe Herranz | 3c839efd2c | |
Felipe Herranz | 8ee110590d | |
Felipe Herranz | fbf3b89b9d | |
Felipe Herranz | 3ad63c9311 | |
Felipe Herranz | d43e1a2edb | |
Felipe Herranz | 6bdbbcb7d8 | |
Raul Bache | f4a4bd95d0 | |
Felipe Herranz | e41b04b906 | |
Felipe Herranz | e80893539a | |
Felipe Herranz | 9dfa8f6867 | |
Felipe Herranz | d280e05043 | |
Felipe Herranz | 8f00b97d1a | |
Felipe Herranz | e99d6b8d56 | |
mws-rmain | 02201fef82 | |
mws-rmain | dce98bb5ea | |
mws-rmain | e7439e3551 | |
mws-rmain | e0af794877 | |
mws-rmain | b5b9a16499 | |
mws-rmain | aa4a19cd46 | |
Felipe Herranz | 77ab67deca | |
Felipe Herranz | ff9f314406 | |
Felipe Herranz | 9a30dfb93b | |
Felipe Herranz | a244d1a36f | |
Felipe Herranz | 72d736bb46 | |
Felipe Herranz | 538a0d2a38 | |
mws-rmain | d5da84072b | |
mws-rmain | 5d619c2e3c | |
mws-rmain | 4141c23813 | |
Felipe Herranz | b2222b0c27 | |
Felipe Herranz | d837762591 | |
Felipe Herranz | baa2db7c17 | |
Felipe Herranz | 4a8e09dbf4 | |
Felipe Herranz | 491bf0c029 |
|
@ -28,3 +28,9 @@ local.properties
|
|||
# Gradle
|
||||
build/
|
||||
.gradle
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
|
|
@ -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).
|
||||
|
13
README.md
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Tue Mar 27 00:15:43 CEST 2018
|
||||
#Mon Dec 14 15:18:57 PST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
UsbSerial Integration Tests
|
||||
===========================
|
||||
For the purpose of helping people contributing to UsbSerial a little set of integration tests have been added. It consists in two parts.
|
||||
- Python script integration.py that sends a series packets (1kb, 2kb, 8kb, 64kb and 128kb) and validates that those packets are received back correctly.
|
||||
- Integration Android app that implements UsbSerial and just receives and sends back the packets sent by the python script.
|
||||
|
||||
Requirements
|
||||
--------------------------------------
|
||||
- Windows/OSX/Linux with Python 3 installed
|
||||
- [PySerial](https://pypi.org/project/pyserial/)
|
||||
- Android phone with Android 3.1 and with USB OTG capabilities
|
||||
|
||||
Steps
|
||||
--------------------------------------
|
||||
Let's say we want to test UsbSerial transmitting at 115200 bauds and our PC port is /dev/ttyUSB0
|
||||
- [Modify UsbService in Integration app to 115200 bauds](https://github.com/felHR85/UsbSerial/blob/integration_tests/integrationapp/src/main/java/com/felhr/integrationapp/UsbService.java#L61).
|
||||
- Compile and install Integration app on your device.
|
||||
- Connect your phone to a serial device at one end and your PC at the other end.
|
||||
- Run python integration.py /dev/ttyUSB0 115200
|
||||
|
||||
Other Scripts
|
||||
--------------------------------------
|
||||
- send_packet.py (python send_packet.py /dev/ttyUSB0 1024 115200)
|
||||
- validate_serial_tx.py (python validate_serial_tx.py /dev/ttyUSB0 1024 115200)
|
|
@ -0,0 +1,34 @@
|
|||
# UsbSerial test: Integration test
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
class style():
|
||||
RED = lambda x: '\033[31m' + str(x)
|
||||
GREEN = lambda x: '\033[32m' + str(x)
|
||||
BLUE = lambda x: '\033[34m' + str(x)
|
||||
RESET = lambda x: '\033[0m' + str(x)
|
||||
|
||||
port = sys.argv[1]
|
||||
speed = sys.argv[2]
|
||||
|
||||
test_sizes = [1024, 2048, 16384, 65535, 131072]
|
||||
|
||||
for i in range(0,5):
|
||||
comm = serial.Serial(port, int(speed))
|
||||
print("Creating " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_tx = os.urandom(test_sizes[i])
|
||||
print("Sending buffer of " + str(test_sizes[i]) + " bytes")
|
||||
comm.write(data_tx)
|
||||
print("Receiving " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_rx = comm.read(test_sizes[i])
|
||||
|
||||
if data_tx == data_rx:
|
||||
print(style.GREEN("Success: " + str(test_sizes[i]) + " bytes buffer was transmitted correctly"))
|
||||
else:
|
||||
print(style.RED("Error: " + str(test_sizes[i]) + " bytes buffer was not transmitted correctly"))
|
||||
print(style.RESET(""))
|
|
@ -0,0 +1,34 @@
|
|||
# UsbSerial test: Integration test
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
class style():
|
||||
RED = lambda x: '\033[31m' + str(x)
|
||||
GREEN = lambda x: '\033[32m' + str(x)
|
||||
BLUE = lambda x: '\033[34m' + str(x)
|
||||
RESET = lambda x: '\033[0m' + str(x)
|
||||
|
||||
port = sys.argv[1]
|
||||
speed = sys.argv[2]
|
||||
|
||||
test_sizes = [1024, 2048, 16384]
|
||||
|
||||
for i in range(0,3):
|
||||
comm = serial.Serial(port, int(speed))
|
||||
print("Creating " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_tx = os.urandom(test_sizes[i])
|
||||
print("Sending buffer of " + str(test_sizes[i]) + " bytes")
|
||||
comm.write(data_tx)
|
||||
print("Receiving " + str(test_sizes[i]) + " bytes buffer")
|
||||
data_rx = comm.read(test_sizes[i])
|
||||
|
||||
if data_tx == data_rx:
|
||||
print(style.GREEN("Success: " + str(test_sizes[i]) + " bytes buffer was transmitted correctly"))
|
||||
else:
|
||||
print(style.RED("Error: " + str(test_sizes[i]) + " bytes buffer was not transmitted correctly"))
|
||||
print(style.RESET(""))
|
|
@ -0,0 +1,21 @@
|
|||
# UsbSerial test: Sending single packet
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# size in bytes (eg 1024)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
port = sys.argv[1]
|
||||
size = sys.argv[2]
|
||||
speed = sys.argv[3]
|
||||
|
||||
comm = serial.Serial(port, int(speed))
|
||||
|
||||
data_tx = os.urandom(int(size))
|
||||
|
||||
bytes_sent = comm.write(data_tx)
|
||||
|
||||
print(str(bytes_sent))
|
|
@ -0,0 +1,35 @@
|
|||
#!bin/bash
|
||||
|
||||
# UsbSerial
|
||||
#
|
||||
# This test generates a number of files specified by the user and send them through the serial port.
|
||||
#
|
||||
# args:
|
||||
# -p: serial port (ttyUSB0, ttyUSB1..)
|
||||
# -b: baud rate
|
||||
# -t: number of times this test will be repeated
|
||||
# -s: size of the random files generated for testing purposes
|
||||
|
||||
while getopts p:t:s:b: OPTION;
|
||||
do
|
||||
case $OPTION
|
||||
in
|
||||
p) PORT=$OPTARG;;
|
||||
t) TIMES=$OPTARG;;
|
||||
s) SIZE=$OPTARG;;
|
||||
b) BAUD=$OPTARG;;
|
||||
esac
|
||||
done
|
||||
|
||||
stty -F $PORT $BAUD
|
||||
|
||||
for i in $(seq 1 $TIMES);
|
||||
do
|
||||
dd if=/dev/urandom of=$i bs=$SIZE count=1 status=none
|
||||
echo "Packet $i of $SIZE was created"
|
||||
cat $i > $PORT
|
||||
echo "Packet $i of $SIZE was sent"
|
||||
|
||||
done
|
||||
|
||||
rm [0-9]*
|
|
@ -0,0 +1,26 @@
|
|||
# UsbSerial test: Validate single packet
|
||||
# args:
|
||||
# port (eg /dev/ttyUSB0)
|
||||
# size in bytes (eg 1024)
|
||||
# speed in bauds (eg 115200)
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import os
|
||||
|
||||
port = sys.argv[1]
|
||||
size = sys.argv[2]
|
||||
speed = sys.argv[3]
|
||||
|
||||
comm = serial.Serial(port, int(speed))
|
||||
|
||||
data_tx = os.urandom(int(size))
|
||||
|
||||
comm.write(data_tx)
|
||||
|
||||
data_rx = comm.read(int(size))
|
||||
|
||||
if data_tx == data_rx:
|
||||
print("Success: Data was transmitted correctly")
|
||||
else:
|
||||
print("Error: Data was not transmitted")
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,39 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.felhr.integrationapp"
|
||||
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
|
||||
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
|
||||
versionName project.VERSION_NAME
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
encoding "UTF-8"
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.support:support-v4:23.1.1'
|
||||
implementation 'com.android.support:appcompat-v7:23.1.1'
|
||||
implementation 'com.android.support:design:23.1.1'
|
||||
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
implementation 'com.squareup.okio:okio:2.1.0'
|
||||
|
||||
implementation project(':usbserial')
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.felhr.integrationapp", appContext.getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.felhr.integrationapp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-feature android:name="android.hardware.usb.host"
|
||||
android:required="true"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service
|
||||
android:name="com.felhr.integrationapp.UsbService"
|
||||
android:enabled="true">
|
||||
</service>
|
||||
<service
|
||||
android:name="com.felhr.integrationapp.UsbSyncService"
|
||||
android:enabled="true">
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_1;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_2;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_3;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_4;
|
||||
import static com.felhr.integrationapp.UsbService.MESSAGE_TEST_5;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private static final int MODE = 0; // 0: Async, 1: Sync, 2: Streams
|
||||
|
||||
/*
|
||||
* Notifications from UsbService will be received here.
|
||||
*/
|
||||
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
switch (intent.getAction()) {
|
||||
case UsbService.ACTION_USB_PERMISSION_GRANTED: // USB PERMISSION GRANTED
|
||||
Toast.makeText(context, "USB Ready", Toast.LENGTH_SHORT).show();
|
||||
statusText.setText("USB connected. Run Python tests");
|
||||
break;
|
||||
case UsbService.ACTION_USB_PERMISSION_NOT_GRANTED: // USB PERMISSION NOT GRANTED
|
||||
Toast.makeText(context, "USB Permission not granted", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_NO_USB: // NO USB CONNECTED
|
||||
Toast.makeText(context, "No USB connected", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_USB_DISCONNECTED: // USB DISCONNECTED
|
||||
Toast.makeText(context, "USB disconnected", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
case UsbService.ACTION_USB_NOT_SUPPORTED: // USB NOT SUPPORTED
|
||||
Toast.makeText(context, "USB device not supported", Toast.LENGTH_SHORT).show();
|
||||
resetTestTextViews();
|
||||
statusText.setText("Connect USB Device");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
private UsbService usbService;
|
||||
private UsbSyncService usbSyncService;
|
||||
private TextView test1, test2, test3, test4, test5;
|
||||
private TextView statusText;
|
||||
private MyHandler mHandler;
|
||||
|
||||
private final ServiceConnection usbConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
|
||||
usbService = ((UsbService.UsbBinder) arg1).getService();
|
||||
usbService.setHandler(mHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
usbService = null;
|
||||
}
|
||||
};
|
||||
|
||||
private final ServiceConnection usbSyncConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
|
||||
usbSyncService = ((UsbSyncService.UsbBinder) arg1).getService();
|
||||
usbSyncService.setHandler(mHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName arg0) {
|
||||
usbSyncService = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
test1 = findViewById(R.id.test_1_result);
|
||||
test2 = findViewById(R.id.test_2_result);
|
||||
test3 = findViewById(R.id.test_3_result);
|
||||
test4 = findViewById(R.id.test_4_result);
|
||||
test5 = findViewById(R.id.test_5_result);
|
||||
statusText = findViewById(R.id.status);
|
||||
mHandler = new MyHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setFilters(); // Start listening notifications from UsbService
|
||||
Toast.makeText(this, "Mode: " + String.valueOf(MODE), Toast.LENGTH_LONG).show();
|
||||
if (MODE == 0) {
|
||||
startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
|
||||
}else if (MODE == 1) {
|
||||
startService(UsbSyncService.class, usbSyncConnection, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mUsbReceiver);
|
||||
if(MODE == 0) {
|
||||
unbindService(usbConnection);
|
||||
}else{
|
||||
unbindService(usbSyncConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {
|
||||
if (!UsbService.SERVICE_CONNECTED) {
|
||||
Intent startService = new Intent(this, service);
|
||||
if (extras != null && !extras.isEmpty()) {
|
||||
Set<String> keys = extras.keySet();
|
||||
for (String key : keys) {
|
||||
String extra = extras.getString(key);
|
||||
startService.putExtra(key, extra);
|
||||
}
|
||||
}
|
||||
startService(startService);
|
||||
}
|
||||
Intent bindingIntent = new Intent(this, service);
|
||||
bindService(bindingIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
private void setFilters() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(UsbService.ACTION_USB_PERMISSION_GRANTED);
|
||||
filter.addAction(UsbService.ACTION_NO_USB);
|
||||
filter.addAction(UsbService.ACTION_USB_DISCONNECTED);
|
||||
filter.addAction(UsbService.ACTION_USB_NOT_SUPPORTED);
|
||||
filter.addAction(UsbService.ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
registerReceiver(mUsbReceiver, filter);
|
||||
}
|
||||
|
||||
private void resetTestTextViews(){
|
||||
test1.setText("TEST1: Not Passed");
|
||||
test2.setText("TEST2: Not Passed");
|
||||
test3.setText("TEST3: Not Passed");
|
||||
test4.setText("TEST4: Not Passed");
|
||||
test5.setText("TEST5: Not Passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* This handler will be passed to UsbService. Data received from serial port is displayed through this handler
|
||||
*/
|
||||
private static class MyHandler extends Handler {
|
||||
private final WeakReference<MainActivity> mActivity;
|
||||
|
||||
public MyHandler(MainActivity activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
String data = (String) msg.obj;
|
||||
switch (msg.what) {
|
||||
case MESSAGE_TEST_1:
|
||||
mActivity.get().test1.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_2:
|
||||
mActivity.get().test2.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_3:
|
||||
mActivity.get().test3.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_4:
|
||||
mActivity.get().test4.setText(data);
|
||||
break;
|
||||
|
||||
case MESSAGE_TEST_5:
|
||||
mActivity.get().test5.setText(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.felhr.usbserial.CDCSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okio.Buffer;
|
||||
|
||||
public class UsbService extends Service {
|
||||
|
||||
public static final String TAG = "UsbService";
|
||||
|
||||
private static final int SIZE_TEST_1 = 1024;
|
||||
private static final int SIZE_TEST_2 = 2048;
|
||||
private static final int SIZE_TEST_3 = 16384;
|
||||
private static final int SIZE_TEST_4 = 65535;
|
||||
private static final int SIZE_TEST_5 = 131072;
|
||||
|
||||
private static final String TEST_1 = "test1";
|
||||
private static final String TEST_2 = "test2";
|
||||
private static final String TEST_3 = "test3";
|
||||
private static final String TEST_4 = "test4";
|
||||
private static final String TEST_5 = "test5";
|
||||
|
||||
|
||||
public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
|
||||
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
|
||||
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
|
||||
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
|
||||
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
|
||||
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
|
||||
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
|
||||
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
|
||||
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
|
||||
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
|
||||
public static final int MESSAGE_TEST_1 = 0;
|
||||
public static final int MESSAGE_TEST_2 = 1;
|
||||
public static final int MESSAGE_TEST_3 = 2;
|
||||
public static final int MESSAGE_TEST_4 = 3;
|
||||
public static final int MESSAGE_TEST_5 = 4;
|
||||
public static final int CTS_CHANGE = 1;
|
||||
public static final int DSR_CHANGE = 2;
|
||||
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
|
||||
private static final int BAUD_RATE = 115200; // BaudRate. Change this value if you need
|
||||
public static boolean SERVICE_CONNECTED = false;
|
||||
|
||||
private IBinder binder = new UsbBinder();
|
||||
|
||||
private Context context;
|
||||
private Handler mHandler;
|
||||
private UsbManager usbManager;
|
||||
private UsbDevice device;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbSerialDevice serialPort;
|
||||
|
||||
private Buffer buffer = new Buffer();
|
||||
private String mode;
|
||||
|
||||
private boolean serialPortConnected;
|
||||
|
||||
|
||||
private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
|
||||
@Override
|
||||
public void onReceivedData(byte[] arg0) {
|
||||
buffer.write(arg0);
|
||||
if(mode.equals(TEST_1)){
|
||||
if(buffer.size() == SIZE_TEST_1){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_2;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_1, "Test 1Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_2)){
|
||||
if(buffer.size() == SIZE_TEST_2){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_3;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_2, "Test 2Kb completed correctly").sendToTarget();
|
||||
}
|
||||
|
||||
}else if(mode.equals(TEST_3)){
|
||||
if(buffer.size() == SIZE_TEST_3){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_4;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_3, "Test 16Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_4)){
|
||||
if(buffer.size() == SIZE_TEST_4){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_5;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_4, "Test 64Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_5)){
|
||||
if(buffer.size() == SIZE_TEST_5){
|
||||
serialPort.write(buffer.readByteArray());
|
||||
mode = TEST_1;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_5, "Test 128Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* State changes in the CTS line will be received here
|
||||
*/
|
||||
private UsbSerialInterface.UsbCTSCallback ctsCallback = new UsbSerialInterface.UsbCTSCallback() {
|
||||
@Override
|
||||
public void onCTSChanged(boolean state) {
|
||||
if(mHandler != null)
|
||||
mHandler.obtainMessage(CTS_CHANGE).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* State changes in the DSR line will be received here
|
||||
*/
|
||||
private UsbSerialInterface.UsbDSRCallback dsrCallback = new UsbSerialInterface.UsbDSRCallback() {
|
||||
@Override
|
||||
public void onDSRChanged(boolean state) {
|
||||
if(mHandler != null)
|
||||
mHandler.obtainMessage(DSR_CHANGE).sendToTarget();
|
||||
}
|
||||
};
|
||||
/*
|
||||
* Different notifications from OS will be received here (USB attached, detached, permission responses...)
|
||||
* About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
|
||||
*/
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent arg1) {
|
||||
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
|
||||
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
|
||||
if (granted) // User accepted our USB connection. Try to open the device as a serial port
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
connection = usbManager.openDevice(device);
|
||||
new ConnectionThread().start();
|
||||
} else // User not accepted our USB connection. Send an Intent to the Main Activity
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
}
|
||||
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
|
||||
if (!serialPortConnected)
|
||||
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
|
||||
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
|
||||
// Usb device was disconnected. send an intent to the Main Activity
|
||||
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
if (serialPortConnected) {
|
||||
serialPort.close();
|
||||
}
|
||||
serialPortConnected = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
|
||||
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.context = this;
|
||||
serialPortConnected = false;
|
||||
UsbService.SERVICE_CONNECTED = true;
|
||||
setFilter();
|
||||
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
findSerialPortDevice();
|
||||
mode = TEST_1;
|
||||
}
|
||||
|
||||
/* MUST READ about services
|
||||
* http://developer.android.com/guide/components/services.html
|
||||
* http://developer.android.com/guide/components/bound-services.html
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
serialPort.close();
|
||||
unregisterReceiver(usbReceiver);
|
||||
UsbService.SERVICE_CONNECTED = false;
|
||||
}
|
||||
|
||||
|
||||
public void setHandler(Handler mHandler) {
|
||||
this.mHandler = mHandler;
|
||||
}
|
||||
|
||||
private void findSerialPortDevice() {
|
||||
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
|
||||
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
|
||||
if (!usbDevices.isEmpty()) {
|
||||
|
||||
// first, dump the hashmap for diagnostic purposes
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
Log.d(TAG, String.format("USBDevice.HashMap (vid:pid) (%X:%X)-%b class:%X:%X name:%s",
|
||||
device.getVendorId(), device.getProductId(),
|
||||
UsbSerialDevice.isSupported(device),
|
||||
device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceName()));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
int deviceVID = device.getVendorId();
|
||||
int devicePID = device.getProductId();
|
||||
|
||||
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) && deviceVID != 0x5c6 && devicePID != 0x904c) {
|
||||
if (UsbSerialDevice.isSupported(device)) {
|
||||
// There is a supported device connected - request permission to access it.
|
||||
requestUserPermission();
|
||||
break;
|
||||
} else {
|
||||
connection = null;
|
||||
device = null;
|
||||
}
|
||||
}
|
||||
if (device==null) {
|
||||
// There are no USB devices connected (but usb host were listed). Send an intent to MainActivity.
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "findSerialPortDevice() usbManager returned empty device list." );
|
||||
// There is no USB devices connected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_USB_PERMISSION);
|
||||
filter.addAction(ACTION_USB_DETACHED);
|
||||
filter.addAction(ACTION_USB_ATTACHED);
|
||||
registerReceiver(usbReceiver, filter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request user permission. The response will be received in the BroadcastReceiver
|
||||
*/
|
||||
private void requestUserPermission() {
|
||||
Log.d(TAG, String.format("requestUserPermission(%X:%X)", device.getVendorId(), device.getProductId() ) );
|
||||
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
usbManager.requestPermission(device, mPendingIntent);
|
||||
}
|
||||
|
||||
public class UsbBinder extends Binder {
|
||||
public UsbService getService() {
|
||||
return UsbService.this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple thread to open a serial port.
|
||||
* Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
|
||||
*/
|
||||
private class ConnectionThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
|
||||
if (serialPort != null) {
|
||||
if (serialPort.open()) {
|
||||
serialPortConnected = true;
|
||||
serialPort.setBaudRate(BAUD_RATE);
|
||||
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
|
||||
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
|
||||
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
|
||||
/**
|
||||
* Current flow control Options:
|
||||
* UsbSerialInterface.FLOW_CONTROL_OFF
|
||||
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
|
||||
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
|
||||
*/
|
||||
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
|
||||
serialPort.read(mCallback);
|
||||
serialPort.getCTS(ctsCallback);
|
||||
serialPort.getDSR(dsrCallback);
|
||||
|
||||
//
|
||||
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
|
||||
// to be uploaded or not
|
||||
//Thread.sleep(2000); // sleep some. YMMV with different chips.
|
||||
|
||||
// Everything went as expected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_USB_READY);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
|
||||
// Send an Intent to Main Activity
|
||||
if (serialPort instanceof CDCSerialDevice) {
|
||||
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No driver for given device, even generic CDC driver could not be loaded
|
||||
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.felhr.usbserial.CDCSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialDevice;
|
||||
import com.felhr.usbserial.UsbSerialInterface;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okio.Buffer;
|
||||
|
||||
/**
|
||||
* Created by Felipe Herranz(felhr85@gmail.com) on 2019-07-04.
|
||||
*/
|
||||
public class UsbSyncService extends Service {
|
||||
|
||||
public static final String TAG = "UsbService";
|
||||
|
||||
private static final int SIZE_TEST_1 = 1024;
|
||||
private static final int SIZE_TEST_2 = 2048;
|
||||
private static final int SIZE_TEST_3 = 16384;
|
||||
|
||||
private static final String TEST_1 = "test1";
|
||||
private static final String TEST_2 = "test2";
|
||||
private static final String TEST_3 = "test3";
|
||||
private static final String TEST_4 = "test4";
|
||||
private static final String TEST_5 = "test5";
|
||||
|
||||
private static final int BUFFER_SYNC = 100;
|
||||
|
||||
|
||||
public static final String ACTION_USB_READY = "com.felhr.connectivityservices.USB_READY";
|
||||
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
|
||||
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
|
||||
public static final String ACTION_USB_NOT_SUPPORTED = "com.felhr.usbservice.USB_NOT_SUPPORTED";
|
||||
public static final String ACTION_NO_USB = "com.felhr.usbservice.NO_USB";
|
||||
public static final String ACTION_USB_PERMISSION_GRANTED = "com.felhr.usbservice.USB_PERMISSION_GRANTED";
|
||||
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "com.felhr.usbservice.USB_PERMISSION_NOT_GRANTED";
|
||||
public static final String ACTION_USB_DISCONNECTED = "com.felhr.usbservice.USB_DISCONNECTED";
|
||||
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "com.felhr.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
|
||||
public static final String ACTION_USB_DEVICE_NOT_WORKING = "com.felhr.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
|
||||
public static final int MESSAGE_TEST_1 = 0;
|
||||
public static final int MESSAGE_TEST_2 = 1;
|
||||
public static final int MESSAGE_TEST_3 = 2;
|
||||
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
|
||||
private static final int BAUD_RATE = 115200; // BaudRate. Change this value if you need
|
||||
public static boolean SERVICE_CONNECTED = false;
|
||||
|
||||
private IBinder binder = new UsbSyncService.UsbBinder();
|
||||
|
||||
private Context context;
|
||||
private Handler mHandler;
|
||||
private UsbManager usbManager;
|
||||
private UsbDevice device;
|
||||
private UsbDeviceConnection connection;
|
||||
private UsbSerialDevice serialPort;
|
||||
|
||||
private Buffer buffer = new Buffer();
|
||||
private String mode;
|
||||
|
||||
private ReadThread readThread;
|
||||
|
||||
private boolean serialPortConnected;
|
||||
|
||||
/*
|
||||
* Different notifications from OS will be received here (USB attached, detached, permission responses...)
|
||||
* About BroadcastReceiver: http://developer.android.com/reference/android/content/BroadcastReceiver.html
|
||||
*/
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context arg0, Intent arg1) {
|
||||
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
|
||||
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
|
||||
if (granted) // User accepted our USB connection. Try to open the device as a serial port
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
connection = usbManager.openDevice(device);
|
||||
new ConnectionThread().start();
|
||||
} else // User not accepted our USB connection. Send an Intent to the Main Activity
|
||||
{
|
||||
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
}
|
||||
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
|
||||
if (!serialPortConnected)
|
||||
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
|
||||
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
|
||||
// Usb device was disconnected. send an intent to the Main Activity
|
||||
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
|
||||
arg0.sendBroadcast(intent);
|
||||
if (serialPortConnected) {
|
||||
serialPort.syncClose();
|
||||
}
|
||||
serialPortConnected = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
|
||||
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
this.context = this;
|
||||
serialPortConnected = false;
|
||||
UsbService.SERVICE_CONNECTED = true;
|
||||
setFilter();
|
||||
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
findSerialPortDevice();
|
||||
mode = TEST_1;
|
||||
}
|
||||
|
||||
/* MUST READ about services
|
||||
* http://developer.android.com/guide/components/services.html
|
||||
* http://developer.android.com/guide/components/bound-services.html
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
serialPort.close();
|
||||
unregisterReceiver(usbReceiver);
|
||||
UsbService.SERVICE_CONNECTED = false;
|
||||
}
|
||||
|
||||
|
||||
public void setHandler(Handler mHandler) {
|
||||
this.mHandler = mHandler;
|
||||
}
|
||||
|
||||
private void findSerialPortDevice() {
|
||||
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
|
||||
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
|
||||
if (!usbDevices.isEmpty()) {
|
||||
|
||||
// first, dump the hashmap for diagnostic purposes
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
Log.d(TAG, String.format("USBDevice.HashMap (vid:pid) (%X:%X)-%b class:%X:%X name:%s",
|
||||
device.getVendorId(), device.getProductId(),
|
||||
UsbSerialDevice.isSupported(device),
|
||||
device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceName()));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
|
||||
device = entry.getValue();
|
||||
int deviceVID = device.getVendorId();
|
||||
int devicePID = device.getProductId();
|
||||
|
||||
// if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003) && deviceVID != 0x5c6 && devicePID != 0x904c) {
|
||||
if (UsbSerialDevice.isSupported(device)) {
|
||||
// There is a supported device connected - request permission to access it.
|
||||
requestUserPermission();
|
||||
break;
|
||||
} else {
|
||||
connection = null;
|
||||
device = null;
|
||||
}
|
||||
}
|
||||
if (device==null) {
|
||||
// There are no USB devices connected (but usb host were listed). Send an intent to MainActivity.
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "findSerialPortDevice() usbManager returned empty device list." );
|
||||
// There is no USB devices connected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_NO_USB);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_USB_PERMISSION);
|
||||
filter.addAction(ACTION_USB_DETACHED);
|
||||
filter.addAction(ACTION_USB_ATTACHED);
|
||||
registerReceiver(usbReceiver, filter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request user permission. The response will be received in the BroadcastReceiver
|
||||
*/
|
||||
private void requestUserPermission() {
|
||||
Log.d(TAG, String.format("requestUserPermission(%X:%X)", device.getVendorId(), device.getProductId() ) );
|
||||
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
usbManager.requestPermission(device, mPendingIntent);
|
||||
}
|
||||
|
||||
public class UsbBinder extends Binder {
|
||||
public UsbSyncService getService() {
|
||||
return UsbSyncService.this;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple thread to open a serial port.
|
||||
* Although it should be a fast operation. moving usb operations away from UI thread is a good thing.
|
||||
*/
|
||||
private class ConnectionThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
|
||||
if (serialPort != null) {
|
||||
if (serialPort.syncOpen()) {
|
||||
serialPortConnected = true;
|
||||
serialPort.setBaudRate(BAUD_RATE);
|
||||
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
|
||||
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
|
||||
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
|
||||
/**
|
||||
* Current flow control Options:
|
||||
* UsbSerialInterface.FLOW_CONTROL_OFF
|
||||
* UsbSerialInterface.FLOW_CONTROL_RTS_CTS only for CP2102 and FT232
|
||||
* UsbSerialInterface.FLOW_CONTROL_DSR_DTR only for CP2102 and FT232
|
||||
*/
|
||||
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
|
||||
|
||||
//
|
||||
// Some Arduinos would need some sleep because firmware wait some time to know whether a new sketch is going
|
||||
// to be uploaded or not
|
||||
//Thread.sleep(2000); // sleep some. YMMV with different chips.
|
||||
|
||||
// Everything went as expected. Send an intent to MainActivity
|
||||
Intent intent = new Intent(ACTION_USB_READY);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
readThread = new ReadThread();
|
||||
readThread.start();
|
||||
} else {
|
||||
// Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
|
||||
// Send an Intent to Main Activity
|
||||
if (serialPort instanceof CDCSerialDevice) {
|
||||
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
} else {
|
||||
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No driver for given device, even generic CDC driver could not be loaded
|
||||
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReadThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
while(true){
|
||||
byte[] tmpBuffer = new byte[16384];
|
||||
int n = serialPort.syncRead(tmpBuffer, 0);
|
||||
|
||||
if(n > 0) {
|
||||
buffer.write(tmpBuffer, 0, n);
|
||||
}
|
||||
|
||||
if(mode.equals(TEST_1)){
|
||||
if(buffer.size() == SIZE_TEST_1){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_2;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_1, "Test 1Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}else if(mode.equals(TEST_2)){
|
||||
if(buffer.size() == SIZE_TEST_2){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_3;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_2, "Test 2Kb completed correctly").sendToTarget();
|
||||
}
|
||||
|
||||
}else if(mode.equals(TEST_3)){
|
||||
if(buffer.size() == SIZE_TEST_3){
|
||||
serialPort.syncWrite(buffer.readByteArray(), 0);
|
||||
mode = TEST_1;
|
||||
mHandler.obtainMessage(MESSAGE_TEST_3, "Test 16Kb completed correctly").sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<vector xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8"/>
|
||||
</vector>
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Integration Tests"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_1_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST1: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_2_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST2: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_3_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST3: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_4_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST4: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/test_5_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:text="TEST5: Not Passed"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Connect USB Device"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Po Szerokość: | Wysokość: | Rozmiar: 2.9 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 4.8 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 2.0 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 2.7 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 4.4 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 6.7 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 6.2 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 10 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 8.9 KiB |
Po Szerokość: | Wysokość: | Rozmiar: 15 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">IntegrationApp</string>
|
||||
</resources>
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,17 @@
|
|||
package com.felhr.integrationapp;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
#Arguments:
|
||||
# -v version eg 6.0.3
|
||||
# -m 6.0.3
|
||||
set -e
|
||||
|
||||
while getopts v:m: OPTION;
|
||||
do
|
||||
case $OPTION
|
||||
in
|
||||
v) VERSION=$OPTARG;;
|
||||
m) MESSAGE=$OPTARG;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Show error message if no version was provided
|
||||
if [[ -z ${VERSION} ]];
|
||||
then
|
||||
echo "UsbSerial: Error!! No version was provided"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show error message if no message was provided
|
||||
if [[ -z ${MESSAGE} ]];
|
||||
then
|
||||
echo "UsbSerial: Error!! No message was provided"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "UsbSerial: Starting Release $VERSION with commit message $MESSAGE"
|
||||
|
||||
VERSION_NAME="VERSION_NAME=$VERSION"
|
||||
|
||||
# Updating gradle.properties with version
|
||||
ex -sc '1d|x' gradle.properties
|
||||
ex -sc "1i|$VERSION_NAME" -cx gradle.properties
|
||||
|
||||
# Updating README file
|
||||
GRADLE_LINE="implementation 'com.github.felHR85:UsbSerial:${VERSION}'"
|
||||
LINE=$(cat README.md | grep -nr implementation\ \'com.github.felHR85:UsbSerial: | awk -F ":" '{print $2}')
|
||||
ex -sc "${LINE}d|x" README.md
|
||||
ex -sc "${LINE}i|$GRADLE_LINE" -cx README.md
|
||||
|
||||
# Gradle clean and build
|
||||
./gradlew clean build
|
||||
|
||||
# Git stuff
|
||||
git add .
|
||||
git commit -m "${MESSAGE}"
|
||||
git tag ${VERSION}
|
||||
git push origin master
|
||||
git push --tags
|
||||
|
||||
echo "UsbSerial: Release Finished!!!"
|
|
@ -1 +1 @@
|
|||
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports'
|
||||
include ':usbserial', ':example', ':examplesync', ':examplestreams', ':examplemultipleports', ':integrationapp'
|
|
@ -19,6 +19,7 @@ android {
|
|||
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
|
||||
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
|
||||
archivesBaseName = "${project.name}-${project.VERSION_NAME}"
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
//noinspection GroovyAssignabilityCheck
|
||||
|
@ -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)
|
||||
|
|
|
@ -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.*
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|