package org.schmivits.airball.airdata; import android.content.Context; import android.hardware.usb.UsbManager; import android.util.Log; import java.io.IOException; import tw.com.prolific.driver.pl2303.PL2303Driver; public class DynonUARTDataSource implements Runnable { private static final String USB_PERMISSION = "org.schmivits.airball.dataproxy.USB_PERMISSION"; private static final int READ_BUFFER_SIZE = 2048; private static final long ENUMERATE_PAUSE = 1000L; private static final long SETUP_PAUSE = 2000L; private static final long READ_PAUSE = 10L; private final Context mContext; private final SerialParameters mSerialParameters; private final HaveData mHaveData; private PL2303Driver mDriver; private final byte[] mReadBuffer = new byte[READ_BUFFER_SIZE]; private final StringBuilder mLineBuilder = new StringBuilder(); private boolean mRunning = true; private Thread mThread; public DynonUARTDataSource(Context context, SerialParameters serialParameters, HaveData haveData) { mContext = context; mSerialParameters = serialParameters; mHaveData = haveData; (mThread = new Thread(this)).start(); } @Override public void run() { mDriver = new PL2303Driver( (UsbManager) mContext.getSystemService(Context.USB_SERVICE), mContext, USB_PERMISSION); boolean doneSetup = false; try { while (mRunning) { if (!mDriver.isConnected()) { doneSetup = false; enumerateDriver(); } else if (mDriver.isConnected() && !doneSetup) { doneSetup = setupDriver(); } else { readFromDriver(); } } } catch (InterruptedException e) { // Interruption is an expected way to terminate Log.i(Constants.LOG_TAG, "Interrupted data read thread, terminating"); } } private void enumerateDriver() throws InterruptedException { if (!mDriver.enumerate()) { Thread.sleep(ENUMERATE_PAUSE); } } private boolean setupDriver() throws InterruptedException { Log.i(Constants.LOG_TAG, "Setting up driver ..."); boolean success; try { int setup = mDriver.setup( mSerialParameters.mBaudRate, mSerialParameters.mDataBits, mSerialParameters.mStopBits, mSerialParameters.mParity, mSerialParameters.mFlowControl); boolean initByBaudRate = mDriver.InitByBaudRate( mSerialParameters.mBaudRate); success = setup == 0 && initByBaudRate; } catch (IOException e) { success = false; Log.e(Constants.LOG_TAG, e.toString()); } if (success) { Log.i(Constants.LOG_TAG, "Setup succeeded"); return true; } else { Log.i(Constants.LOG_TAG, "Setup failed, sleeping ..."); Thread.sleep(SETUP_PAUSE); return false; } } private void readFromDriver() throws InterruptedException { for (int n; (n = mDriver.read(mReadBuffer)) > 0; ) { receivedData(n); } Thread.sleep(READ_PAUSE); } private boolean isLineSeparator(char c) { return c == '\r' || c == '\n'; } private void receivedData(int n) { for (int i = 0; i < n; i++) { char c = (char) mReadBuffer[i]; if (isLineSeparator(c)) { if (mLineBuilder.length() > 0) { mHaveData.line(mLineBuilder.toString()); mLineBuilder.setLength(0); } } else { mLineBuilder.append(c); } } } public void destroy() { mThread.interrupt(); mDriver.end(); mRunning = false; } }