參考http://stackoverflow.com/questions/25662307/android-l-libusb-init-returns-libusb-error-other-99 html
http://stackoverflow.com/questions/8854359/exception-open-failed-eacces-permission-denied-on-android java
和http://www.freehum.com/2014/06/operate-usb-device-under-android-by-libusb-without-root.htmllinux
在將原來的程序(Android 4.x)部署到Android 5.0和6.0的時候,遇到libusb_init失敗和open failed (Permission denied)的錯誤,Google以後,發現是權限問題。android
Android 5.0以後強制開啓了Selinux:git
Android sandbox reinforced with SELinux. Android now requires SELinux in enforcing mode for all domains. SELinux is a mandatory access control (MAC) system in the Linux kernel used to augment the existing discretionary access control (DAC) security model. This new layer provides additional protection against potential security vulnerabilities.github
詳見https://source.android.com/security/enhancements/enhancements50.html dom
解決辦法有2種tcp
安裝SELinuxModeChanger,將模式改成permissive —— 貌似須要rootide
修改libusb,stackoverflow上說以下2個連接已經fix了:https://github.com/martinmarinov/rtl_tcp_andro-和https://github.com/Gritzman/libusb函數
本人使用的https://github.com/Gritzman/libusb
另外,可能須要增長libusb_open_fd,編譯以後的so見http://pan.baidu.com/s/1hrzAfZ2
1) core.c 中在 libusb_open 後面增長 libusb_open_fd 函數
int API_EXPORTED 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; }
2) os/linux_usbfs.c 中在 op_open 後面增長 op_open_fd 函數
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); }
3)os/linux_usbfs.c中.open = op_open,後添加.open_fd = op_open_fd,
4) 在libusbi.h中,
int (*open)(struct libusb_device_handle *handle);
後添加
int (*open_fd)(struct libusb_device_handle *handle, int fd);
API 23(6.0)以後,須要請求讀寫外設權限
private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; //在須要讀寫外設的地方 int permission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user requestPermissions(PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE); }