libusb_init失敗及open failed (Permission denied)

參考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

libusb_init失敗(error -99)

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

  1. 安裝SELinuxModeChanger,將模式改成permissive —— 貌似須要rootide

  2. 修改libusb,stackoverflow上說以下2個連接已經fix了:https://github.com/martinmarinov/rtl_tcp_andro-https://github.com/Gritzman/libusb函數

  3. 本人使用的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);

'open failed: EACCES (Permission denied)' 

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);
    }
相關文章
相關標籤/搜索