是什么导致 UsbRequest 从队列方法中抛出 IO 异常?

What causes UsbRequest to throw IO Exception from queue method?

我正在尝试使用 Mike Wakerly 的 usb-serial-for-android 库通过 USB 串口与 Arduino Mega 克隆进行通信(谢谢!)我已经解决了权限错误,但是现在我遇到了以下问题:

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)

方法如下。抛出错误的行是带有 !request.queue(buf, dest.length)

的 if 循环
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;
    }

之前,他的 CdcAcmSerialDriver.java 第 319 行似乎有一个错误: mDataInterface = mDevice.getInterface(1);

所以我将 1 更改为 0,这修复了基于 的索引越界错误。最后将他所有的 .java 文件移动到我的包中以便对其进行编辑。甚至不确定这是否相关。

目前,我的应用程序在发生该异常后挂起。底线:我在低级代码中游来游去,运行 出局了。你能给我指点陆地吗:)?

所以在包括 Chromium 在内的所有代码示例中,none 实际上检查了 request.queue 的结果。看这里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.");
}

所以在代码内部,只要有异常,SerialInputOutputManager 就会停止,所以最好的办法是在出错时重新运行它。

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

或者将其修改为不 运行 异常,但是 requestWait 很可能 return 为空。

如果我想出一个天才的解决方案,它会在我的 github 项目中使用相同的库。