diff --git a/example/src/main/java/com/felhr/serialportexample/UsbService.java b/example/src/main/java/com/felhr/serialportexample/UsbService.java index b1639cd..0efac01 100644 --- a/example/src/main/java/com/felhr/serialportexample/UsbService.java +++ b/example/src/main/java/com/felhr/serialportexample/UsbService.java @@ -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 usbDevices = usbManager.getDeviceList(); if (!usbDevices.isEmpty()) { - boolean keep = true; + + // 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) { - - // 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); } diff --git a/examplestreams/src/main/java/com/felhr/examplestreams/UsbService.java b/examplestreams/src/main/java/com/felhr/examplestreams/UsbService.java index df89c60..f53ec19 100644 --- a/examplestreams/src/main/java/com/felhr/examplestreams/UsbService.java +++ b/examplestreams/src/main/java/com/felhr/examplestreams/UsbService.java @@ -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 usbDevices = usbManager.getDeviceList(); if (!usbDevices.isEmpty()) { - boolean keep = true; + + // first, dump the map 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)) { +// 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); } } -} \ No newline at end of file +} diff --git a/examplesync/src/main/java/com/felhr/serialportexamplesync/UsbService.java b/examplesync/src/main/java/com/felhr/serialportexamplesync/UsbService.java index d1d962f..2bccdcf 100644 --- a/examplesync/src/main/java/com/felhr/serialportexamplesync/UsbService.java +++ b/examplesync/src/main/java/com/felhr/serialportexamplesync/UsbService.java @@ -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 usbDevices = usbManager.getDeviceList(); if (!usbDevices.isEmpty()) { - boolean keep = true; + + // first, dump the map 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)) { +// 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); } diff --git a/usbserial/src/main/java/com/felhr/usbserial/AbstractWorkerThread.java b/usbserial/src/main/java/com/felhr/usbserial/AbstractWorkerThread.java new file mode 100644 index 0000000..e046e84 --- /dev/null +++ b/usbserial/src/main/java/com/felhr/usbserial/AbstractWorkerThread.java @@ -0,0 +1,18 @@ +package com.felhr.usbserial; + +abstract class AbstractWorkerThread extends Thread { + boolean firstTime = true; + private volatile boolean keep = true; + + void stopThread() { + keep = false; + } + + public final void run() { + while (keep) { + doRun(); + } + } + + abstract void doRun(); +} diff --git a/usbserial/src/main/java/com/felhr/usbserial/BLED112SerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/BLED112SerialDevice.java index 85ad9ea..91dbaf4 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/BLED112SerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/BLED112SerialDevice.java @@ -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 diff --git a/usbserial/src/main/java/com/felhr/usbserial/CDCSerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/CDCSerialDevice.java index 95ee03d..08bbe5f 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/CDCSerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/CDCSerialDevice.java @@ -46,10 +46,9 @@ 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 initialBaudRate = 0; @@ -84,7 +83,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 diff --git a/usbserial/src/main/java/com/felhr/usbserial/CH34xSerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/CH34xSerialDevice.java index 640db2b..d239b7c 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/CH34xSerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/CH34xSerialDevice.java @@ -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(); @@ -85,7 +83,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 +115,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 @@ -609,66 +606,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() diff --git a/usbserial/src/main/java/com/felhr/usbserial/CP2102SerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/CP2102SerialDevice.java index f4e8be8..ce5d2c6 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/CP2102SerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/CP2102SerialDevice.java @@ -10,8 +10,6 @@ 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(); @@ -67,10 +65,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 +100,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 @@ -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() diff --git a/usbserial/src/main/java/com/felhr/usbserial/CP2130SpiDevice.java b/usbserial/src/main/java/com/felhr/usbserial/CP2130SpiDevice.java index 0e43327..539a515 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/CP2130SpiDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/CP2130SpiDevice.java @@ -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; diff --git a/usbserial/src/main/java/com/felhr/usbserial/FTDISerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/FTDISerialDevice.java index b100c28..e6a6f92 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/FTDISerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/FTDISerialDevice.java @@ -79,10 +79,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; @@ -117,7 +116,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 diff --git a/usbserial/src/main/java/com/felhr/usbserial/PL2303SerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/PL2303SerialDevice.java index 2680f52..fa7b00a 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/PL2303SerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/PL2303SerialDevice.java @@ -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 diff --git a/usbserial/src/main/java/com/felhr/usbserial/SerialBuffer.java b/usbserial/src/main/java/com/felhr/usbserial/SerialBuffer.java index 407c073..4b7309b 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/SerialBuffer.java +++ b/usbserial/src/main/java/com/felhr/usbserial/SerialBuffer.java @@ -11,6 +11,7 @@ public class SerialBuffer 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[] readBufferCompatible; // Read buffer for android < 4.2 private boolean debugging = false; diff --git a/usbserial/src/main/java/com/felhr/usbserial/SerialInputStream.java b/usbserial/src/main/java/com/felhr/usbserial/SerialInputStream.java index 8c1be0c..afa8448 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/SerialInputStream.java +++ b/usbserial/src/main/java/com/felhr/usbserial/SerialInputStream.java @@ -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; diff --git a/usbserial/src/main/java/com/felhr/usbserial/SerialPortBuilder.java b/usbserial/src/main/java/com/felhr/usbserial/SerialPortBuilder.java index 923cdf7..70374bd 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/SerialPortBuilder.java +++ b/usbserial/src/main/java/com/felhr/usbserial/SerialPortBuilder.java @@ -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 devices; private List serialDevices = new ArrayList<>(); - private ArrayBlockingQueue queuedPermissions = new ArrayBlockingQueue<>(100); - private AtomicBoolean processingPermission = new AtomicBoolean(false); + private final ArrayBlockingQueue 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(); } } @@ -164,13 +161,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 +201,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 +219,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 +234,7 @@ public class SerialPortBuilder { private class InitSerialPortThread extends Thread { - private List usbSerialDevices; + private final List usbSerialDevices; public InitSerialPortThread(List usbSerialDevices) { this.usbSerialDevices = usbSerialDevices; diff --git a/usbserial/src/main/java/com/felhr/usbserial/UsbSerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/UsbSerialDevice.java index d2bb509..0066a76 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/UsbSerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/UsbSerialDevice.java @@ -1,7 +1,5 @@ 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; @@ -22,10 +20,9 @@ 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; + private static final boolean mr1Version; protected final UsbDevice device; protected final UsbDeviceConnection connection; @@ -304,52 +301,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) usbSerialDevice).ftdiUtilities.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 +365,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 +403,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) usbSerialDevice).ftdiUtilities.adaptArray(dataReceived); onReceivedData(dataReceived); } + }else + { + onReceivedData(dataReceived); } } } @@ -473,11 +440,6 @@ public abstract class UsbSerialDevice implements UsbSerialInterface this.inEndpoint = inEndpoint; } - public void stopReadThread() - { - working.set(false); - } - private void onReceivedData(byte[] data) { if(callback != null) @@ -511,11 +473,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,7 +504,7 @@ public abstract class UsbSerialDevice implements UsbSerialInterface { if(writeThread != null) { - writeThread.stopWriteThread(); + writeThread.stopThread(); writeThread = null; } } diff --git a/usbserial/src/main/java/com/felhr/usbserial/UsbSpiDevice.java b/usbserial/src/main/java/com/felhr/usbserial/UsbSpiDevice.java index 63b1677..2ec3f69 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/UsbSpiDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/UsbSpiDevice.java @@ -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,7 +174,7 @@ public abstract class UsbSpiDevice implements UsbSpiInterface { if(writeThread != null) { - writeThread.stopWriteThread(); + writeThread.stopThread(); writeThread = null; } } diff --git a/usbserial/src/main/java/com/felhr/usbserial/XdcVcpSerialDevice.java b/usbserial/src/main/java/com/felhr/usbserial/XdcVcpSerialDevice.java index 799cff7..e84492b 100644 --- a/usbserial/src/main/java/com/felhr/usbserial/XdcVcpSerialDevice.java +++ b/usbserial/src/main/java/com/felhr/usbserial/XdcVcpSerialDevice.java @@ -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