diff --git a/README.md b/README.md
index 90ff83f..b2f80d0 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,8 @@ UsbSerial wiki available. Read it first
[**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)\
-[**Debugging over Wifi**](https://github.com/felHR85/UsbSerial/wiki/9.-Debugging-over-Wifi)
+[**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)
Support UsbSerial
--------------------------------------
diff --git a/integrationapp/src/main/AndroidManifest.xml b/integrationapp/src/main/AndroidManifest.xml
index 9455d46..17f00d5 100644
--- a/integrationapp/src/main/AndroidManifest.xml
+++ b/integrationapp/src/main/AndroidManifest.xml
@@ -23,6 +23,10 @@
android:name="com.felhr.integrationapp.UsbService"
android:enabled="true">
+
+
diff --git a/integrationapp/src/main/java/com/felhr/integrationapp/MainActivity.java b/integrationapp/src/main/java/com/felhr/integrationapp/MainActivity.java
index 93a1fe2..23076f2 100644
--- a/integrationapp/src/main/java/com/felhr/integrationapp/MainActivity.java
+++ b/integrationapp/src/main/java/com/felhr/integrationapp/MainActivity.java
@@ -25,6 +25,8 @@ 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.
*/
@@ -60,6 +62,7 @@ public class MainActivity extends AppCompatActivity {
}
};
private UsbService usbService;
+ private UsbSyncService usbSyncService;
private TextView test1, test2, test3, test4, test5;
private TextView statusText;
private MyHandler mHandler;
@@ -77,6 +80,19 @@ public class MainActivity extends AppCompatActivity {
}
};
+ 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);
@@ -94,7 +110,11 @@ public class MainActivity extends AppCompatActivity {
public void onResume() {
super.onResume();
setFilters(); // Start listening notifications from UsbService
- startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
+ 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
diff --git a/integrationapp/src/main/java/com/felhr/integrationapp/UsbSyncService.java b/integrationapp/src/main/java/com/felhr/integrationapp/UsbSyncService.java
new file mode 100644
index 0000000..14e622f
--- /dev/null
+++ b/integrationapp/src/main/java/com/felhr/integrationapp/UsbSyncService.java
@@ -0,0 +1,327 @@
+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 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";
+
+ 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;
+ 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 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 usbDevices = usbManager.getDeviceList();
+ if (!usbDevices.isEmpty()) {
+
+ // first, dump the hashmap for diagnostic purposes
+ for (Map.Entry 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 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[BUFFER_SYNC];
+ int n = serialPort.syncRead(tmpBuffer, 0);
+
+ if(n > 0) {
+ buffer.write(tmpBuffer);
+ }
+
+ 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_4;
+ mHandler.obtainMessage(MESSAGE_TEST_3, "Test 16Kb completed correctly").sendToTarget();
+ }
+ }else if(mode.equals(TEST_4)){
+ if(buffer.size() == SIZE_TEST_4){
+ serialPort.syncWrite(buffer.readByteArray(), 0);
+ 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.syncWrite(buffer.readByteArray(), 0);
+ mode = TEST_1;
+ mHandler.obtainMessage(MESSAGE_TEST_5, "Test 128Kb completed correctly").sendToTarget();
+ }
+ }
+ }
+ }
+ }
+}