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 :)?

1
  • Ha! I'm now in the same boat, will let you know what I find. Commented Sep 10, 2015 at 1:45

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help! This project is a little dormant at the moment, but I will keep you posted on results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.