Hello there! It’s been a while since my last post, and I’m back here again.
Today I’d like to write a small note about the USB Android Open Accessory protocol. In short, it allows an android device to communicate with external devices over USB, even if it can’t be a host. When using it on Android, I got an IOException with EBADF code. What to do?
First of all, I had used this very helpful page with sources as the basis for both parts (Android and computer): http://android.serverbox.ch/?p=262.
The stacktrace I got when trying to send data after a certain delay looks like this:
1234567891011
java.io.IOException: write failed: EBADF (Bad file number)
at libcore.io.IoBridge.write(IoBridge.java:452)
at java.io.FileOutputStream.write(FileOutputStream.java:187)
β¦
Caused by: libcore.io.ErrnoException: write failed: EBADF (Bad file number)
at libcore.io.Posix.writeBytes(Native Method)
at libcore.io.Posix.write(Posix.java:178)
at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
at libcore.io.IoBridge.write(IoBridge.java:447)
at java.io.FileOutputStream.write(FileOutputStream.java:187)
β¦
When opening a USB accessory, I saved the references to the following variables required for communication:
123456
// the opened USB accessoryprivateUsbAccessorymAccessory=null;// stream to read data fromprivateInputStreammInputStream=null;// stream to write data toprivateOutputStreammOutputStream=null;
Long story short, turned out the parent FileDescriptor got garbage collected and thus invalid, causing the aforementioned exception. So I need to keep
try{mParcelFD=getUsbManager().openAccessory(mAccessory);}catch(SecurityExceptione){finalStringmsg="Have no permission to open the accessory";logE(msg,e);returnfalse;}if(mParcelFD==null){logW("Can't open accessory!");returnfalse;}FileDescriptorfd=mParcelFD.getFileDescriptor();mInputStream=newFileInputStream(fd);mOutputStream=newFileOutputStream(fd);
All in all, the AOA protocol seems to be somewhat incomplete. For example, when one end disconnects, the other one doesn’t get notified. In case of Android code, the read() call is blocking and cannot be interrupted only by new data or physical USB disconnect. But that’s another storyβ¦