为了账号安全,请及时绑定邮箱和手机立即绑定

USBFS IOCTL 调用 witn JNA 在 64 位架构中不起作用

USBFS IOCTL 调用 witn JNA 在 64 位架构中不起作用

冉冉说 2023-03-31 17:10:59
在 Android 中,我使用一个类 ( UsbIso.java ) 从连接的 USB 设备以同步方式传输数据。由于 Android 本身不支持同步传输,我不得不通过 JNA 库使用 USBFS 原生 Linux 机制来进行正确的 ioctl 调用。在具有 32 位架构(armeabi、armeabi-v7a)的 Android 设备中,一切正常。在具有 64 位架构 (arm64-v8a) 的 Android 设备中,ioctl 调用 reap URB(USBDEVFS_REAPURB,在 reapRequest 方法内部,请参见下面的相关代码)返回错误 14,地址错误。我猜这是由 USBDEVFS_REAPURB 参数或 PointerByReference 参数引起的,它指向一个无效的虚拟地址,但我不知道如何解决它。UsbIso.java类中导致该错误的相关代码是这样的:public Request reapRequest (boolean wait) throws IOException {        PointerByReference urbPointer = new PointerByReference();        int func = wait ? USBDEVFS_REAPURB : USBDEVFS_REAPURBNDELAY;        int rc;        try {            rc = libc.ioctl(fileDescriptor, func, urbPointer);  // <-- Error 14, bad address        } catch (LastErrorException e) {            if (e.getErrorCode() == EAGAIN && !wait) {                return null;             }        }...}
查看完整描述

1 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

您正在使用针对 32 位优化的源代码:


// Note: The layout and size of the USBFS structures matches that of Linux Kernel 3.2 and 3.14

// for ARM 32 bit. For other environments (X86, 64 bit, future Linux kernels), it might be

// necessary to adjust some values.

虽然 JNA 通常会针对 32 位和 64 位调整结构映射,但此代码认为 JNA 太慢并手动映射这些偏移量:


// This class is modeled after struct usbdevfs_urb in <linuxKernel>/include/linux/usbdevice_fs.h

// At first I implemented the URB structure directly using com.sun.jna.Structure, but that was extremely slow.

// Therefore byte offsets are now used to access the fields of the structure.

如果您查看结构映射,usbdevfs_urb有 3 个指针字段需要从 4 字节偏移量调整为 8 字节偏移量。例如,第 5 个字段buffer从 4 个字节变为 8 个字节,因此此代码中断:


   public void setBuffer (Pointer buffer) {

      urbBuf.putInt(12, (int)Pointer.nativeValue(buffer)); }

   public void setBufferLength (int bufferLength) {

      urbBuf.putInt(16, bufferLength); }

特别是,putInt(12, (int) ...)可能应该是putLong(12, ...),下一次调用中的 16 应该是 20(依此类推,将 4 添加到剩余的偏移量中。)


最后两个字段也是 8 字节 vs. 4 字节,所以 andsetUserContext()需要getUserContext()处理long而不是intandurbBaseSize需要从 44 递增到 52(+4 为buffer,+4 为userContext.


我看到一些其他int变量代表需要变成longs 的内存地址。我可能错过了其他需要的更改。


查看完整回答
反对 回复 2023-03-31
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

正如 Peter Stoiber 在这个问题的最后一个答案中所述,存在一个解决这个问题的类:https ://github.com/Peter-St/Android-UVC-Camera/tree/master/app/src/main /java/humer/uvc_camera/UsbIso64


查看完整回答
反对 回复 2023-03-31
  • 1 回答
  • 0 关注
  • 229 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信