Android 用 libusb 操作 USB 设备,无须 root
16lz
2021-01-23
http://www.freehum.com/2014/06/operate-usb-device-under-android-by-libusb-without-root.html
对原作者做了一定的改进
之前有段时间在 Android 下调用我们自己开发的 USB 摄像头,在 CSDN 上讨论了一番,发现感兴趣的人蛮多了,不断网友发邮件来问,干脆放到博客上吧
基本思路:
利用 Android (3.1版本以上)的 USB HOST API 获得 USB 设备的 FileDescriptor,然后libusb 使用 FileDescriptor 打开 USB 设备,当然 libusb 需要做少量修改,后面有代码。
总体的效果就是,用户插入USB 设备,或者启动 Android 系统,你的 App 会根据事先设定的 device filter 自动启动。如果是第一次启动,会询问用户是否授权使用该USB设备。
关键代码(如何使用libusb,请参考官方文档):
获取 FileDescriptor// get FileDescriptor by Android USB Host APIUsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";HashMap deviceList = manager.getDeviceList();Iterator deviceIterator = deviceList.values().iterator(); PendingIntent mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);mContext.registerReceiver(mUsbReceiver, filter); int fd = -1;while(deviceIterator.hasNext()){ UsbDevice device = deviceIterator.next(); Log.i(TAG, device.getDeviceName() + " " + Integer.toHexString(device.getVendorId()) + " " + Integer.toHexString(device.getProductId())); manager.requestPermission(device, mPermissionIntent); UsbDeviceConnection connection = manager.openDevice(device); if(connection != null){ fd = connection.getFileDescriptor(); } else Log.e(TAG, "UsbManager openDevice failed"); break;}
接着修改 libusb,我用的是libusbx-1.0.17,主要工作是增加一个 libusb_open_fd 函数,替代原来的 libusb_open,将上一步的 fd 传入即可。 libusbx\libusb\core.c 中在 libusb_open 后面增加 libusb_open_fd 函数
#ifdef ANDROIDint LIBUSB_CALL libusb_open_fd(libusb_device *dev, libusb_device_handle **handle, int fd){struct libusb_context *ctx = DEVICE_CTX(dev);struct libusb_device_handle *_handle;size_t priv_size = usbi_backend->device_handle_priv_size;int r;usbi_dbg("open %d.%d", dev->bus_number, dev->device_address); _handle = malloc(sizeof(*_handle) + priv_size);if (!_handle)return LIBUSB_ERROR_NO_MEM; r = usbi_mutex_init(&_handle->lock, NULL);if (r) {free(_handle);return LIBUSB_ERROR_OTHER;} _handle->dev = libusb_ref_device(dev);_handle->claimed_interfaces = 0;memset(&_handle->os_priv, 0, priv_size); r = usbi_backend->open_fd(_handle, fd);if (r < 0) {usbi_dbg("open %d.%d returns %d", dev->bus_number, dev->device_address, r);libusb_unref_device(dev);usbi_mutex_destroy(&_handle->lock);free(_handle);return r;} usbi_mutex_lock(&ctx->open_devs_lock);list_add(&_handle->list, &ctx->open_devs);usbi_mutex_unlock(&ctx->open_devs_lock);*handle = _handle; /* At this point, we want to interrupt any existing event handlers so * that they realise the addition of the new device's poll fd. One * example when this is desirable is if the user is running a separate * dedicated libusb events handling thread, which is running with a long * or infinite timeout. We want to interrupt that iteration of the loop, * so that it picks up the new fd, and then continues. */usbi_fd_notification(ctx); return 0;}#endif
在libusbx\libusb\libusb.h中找到libusb_open函数的声明,在其下面添加libusb_open_fd声明:
int LIBUSB_CALL libusb_open_fd(libusb_device *dev, libusb_device_handle **handle, int fd);
在libusbx\libusb\libusbi.h中找到结构体usbi_os_backend,在其内部成员open下面添加int (*open_fd)(struct libusb_device_handle *handle, int fd);
libusbx\libusb\os\linux_usbfs.c 中在 op_open 后面增加 op_open_fd 函数 #ifdef ANDROID//可以去掉,否则要到config.h中去定义才能是同static int op_open_fd(struct libusb_device_handle *handle, int fd) {struct linux_device_handle_priv *hpriv = _device_handle_priv(handle); hpriv->fd = fd; return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);}#endif
libusbx\libusb\os\linux_usbfs.c 中在 结构体 linux_usbfs_backend 中 .open = op_open 一行后面增加一行 #ifdef ANDROID//可以去掉,否则要到config.h中去定义才能是同 .open_fd = op_open_fd,#endif
更多相关文章
- Android 自定义Toast
- android UI学习 -- 设置界面的布局(包括style的使用,selector的
- Android SDK自定义更新
- Android Bluetooth蓝牙开发:Bluetooth蓝牙设备之间数据传输(4)
- 安卓自定义interpolator
- [置顶] 定义一个ImageVIew出现警告的去除办法
- 可自定义 View 的 Toast