Android应用利用libusb与usb设备通信遇到的权限问题

时间:2021-02-06 16:11:55

有2种方法:

1.chmod 666 dev/bus/usb/*


2.如果没有android root权限那就麻烦一点,描述个大概

AndroidManifest.xml中添加:

<uses-feature android:name="android.hardware.usb.host" android:required="true"/>

...

<uses-permission android:name="android.hardware.usb.host" />  
<uses-permission android:name="ANDROID.PERMISSION.HARDWARE_TEST" /> 

...

<intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />

 </intent-filter>
 <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" /> 

device_filter.xml内容:

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <usb-device vendor-id="1204" product-id="34323" /> 
    <usb-device vendor-id="1204" product-id="241" />
</resources>

//确认需要通信的usb devide的vid和pid。确认这里是十进制。

代码中用usbManager open你需要open的设备然后获取fd。这个fd是关键,通过jni把fd传进libusb:

UsbDeviceConnection usbDeviceC = manager.openDevice(mUsbDevice);
int fd = usbDeviceC.getFileDescriptor();

--------------------jni------------------------传递fd进libusb,修改libusb接口

ibusb_device_handle *h = NULL;

h = libusb_open_device_with_vid_pid(p_ctx, vid, pid, fd);

libusb_control_transfer(h, 0x40, vendor_command, address, 0x00, dbuf, num_bytes, 1000);

.....

libusb  在core.c中添加

DEFAULT_VISIBILITY
libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
libusb_context *ctx, uint16_t vendor_id, uint16_t product_id,int fd)
{
struct libusb_device **devs;
struct libusb_device *found = NULL;
struct libusb_device *dev;
struct libusb_device_handle *handle = NULL;
size_t i = 0;
int r;


if (libusb_get_device_list(ctx, &devs) < 0)
return NULL;


while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
goto out;
if (desc.idVendor == vendor_id && desc.idProduct == product_id) {
found = dev;
break;
}
}


if (found) {
r = libusb_open_fd(found, &handle,fd);
if (r < 0)
handle = NULL;
}


out:
libusb_free_device_list(devs, 1);
return handle;
}

int 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;  
}  

在linux_usbfs.c中添加

const struct usbi_os_backend linux_usbfs_backend = {

...

.open_fd = 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);
int r;
hpriv->fd = fd;

if (hpriv->fd < 0) {
if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
/* device will still be marked as attached if hotplug monitor thread
* hasn't processed remove event yet */
usbi_mutex_static_lock(&linux_hotplug_lock);
if (handle->dev->attached) {
usbi_dbg("open failed with no device, but device still attached");
linux_device_disconnected(handle->dev->bus_number,
handle->dev->device_address, NULL);
}
usbi_mutex_static_unlock(&linux_hotplug_lock);
}
return hpriv->fd;
}


r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
if (r < 0) {
if (errno == ENOTTY)
usbi_dbg("getcap not available");
else
usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno);
hpriv->caps = 0;
if (supports_flag_zero_packet)
hpriv->caps |= USBFS_CAP_ZERO_PACKET;
if (supports_flag_bulk_continuation)
hpriv->caps |= USBFS_CAP_BULK_CONTINUATION;
}


return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
}

libusb.h libusbi.h中添加

int LIBUSB_CALL libusb_open_fd(libusb_device *dev, libusb_device_handle **handle, int fd);

libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
libusb_context *ctx, uint16_t vendor_id, uint16_t product_id,int fd);

int (*open_fd)(struct libusb_device_handle *handle, int fd);


总结一句关键hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);变成了hpriv->fd=fd从上层传递下来的fd,这样android应用就可以操作ioctl了。