0

I'm attempting to communicate with an Arduino Mega clone via USB Serial using Mike Wakerly's usb-serial-for-android library (thank you!) I've already dug through the permissions errors, but now I'm getting the following problem:

09-02 15:08:03.628  18694-18792/org.drivebuv.buvmonitor W/SerialInputOutputManager﹕ Run ending due to exception: Error queueing request.
java.io.IOException: Error queueing request.
        at org.drivebuv.buvmonitor.CdcAcmSerialDriver$CdcAcmSerialPort.read(CdcAcmSerialDriver.java:168)
        at org.drivebuv.buvmonitor.SerialInputOutputManager.step(SerialInputOutputManager.java:158)
        at org.drivebuv.buvmonitor.SerialInputOutputManager.run(SerialInputOutputManager.java:140)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)

The method follows below. The line throwing the error is the if-loop with !request.queue(buf, dest.length)

public int read(byte[] dest, int timeoutMillis) throws IOException {
        if (mEnableAsyncReads) {
          final UsbRequest request = new UsbRequest();
          try {
            request.initialize(mConnection, mReadEndpoint);
            final ByteBuffer buf = ByteBuffer.wrap(dest);
            if (!request.queue(buf, dest.length)) {
              throw new IOException("Error queueing request.");
            }

            final UsbRequest response = mConnection.requestWait();
            if (response == null) {
              throw new IOException("Null response");
            }

            final int nread = buf.position();
            if (nread > 0) {
              Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
              return nread;
            } else {
              return 0;
            }
          } finally {
            request.close();
          }
        }

        final int numBytesRead;
        synchronized (mReadBufferLock) {
            int readAmt = Math.min(dest.length, mReadBuffer.length);
            numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
                    timeoutMillis);
            if (numBytesRead < 0) {
                // This sucks: we get -1 on timeout, not 0 as preferred.
                // We *should* use UsbRequest, except it has a bug/api oversight
                // where there is no way to determine the number of bytes read
                // in response :\ -- http://b.android.com/28023
                if (timeoutMillis == Integer.MAX_VALUE) {
                    // Hack: Special case "~infinite timeout" as an error.
                    return -1;
                }
                return 0;
            }
            System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
        }
        return numBytesRead;
    }

Previously, there seemed to be a a bug in his CdcAcmSerialDriver.java on line 319: mDataInterface = mDevice.getInterface(1);

So I changed that 1 to a 0, which fixed an index out-of-bounds error, based on How to fix java.lang.ArrayIndexOutOfBoundsException: length=1; index=1. Ended up moving all his .java files into my package in order to edit them. Not even sure if that's relevant.

At the moment, my app hangs after that exception. Bottom line: I'm swimming in low-level code here and running out of kludges. Would you kindly point me towards land :)?

Community
  • 1
  • 1

1 Answers1

2

So in all the code examples including Chromium, none of them actually check the result of request.queue. See here http://src.chromium.org/chrome/trunk/src/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java

if (!request.queue(buf, dest.length)) {
          throw new IOException("Error queueing request.");
}

So inside the code whenever there is an exception SerialInputOutputManager stops, So the best bet is to re-run it on error.

@Override
  public void onRunError(Exception e) {
   Log.d(TAG, "Runner stopped.");
   //restart if the error is the queue
}

Or hack it to not run an exception however requestWait will most likely return null.

If I come up with a genius solution to this it will me on my github project which is using this same library.

Mikey0000
  • 96
  • 3