尝试访问USB设备时libusb_open_device_with_vid_pid失败

时间:2015-06-04 16:43:21

标签: java android android-ndk java-native-interface libusb-1.0

我正在尝试将USB设备连接到Android 5.1.1设备。以前我一直在使用常规的libusb for KitKat,但Lollipop增加了安全性,这已不再适用。

这是有据可查的,要求root设置SELinux级别。我不想让设备生根以使USB设备连接到它。

环顾四周后,我遇到了this answer并尝试了this libusb fork,但现在我收到了新的错误

libusb_open_device_with_vid_pid (29c2) failed.
Failed to setup USB
usb_setup: -1

我没有更改任何代码,只更改了库。

这仍然是一个许可问题,或者是否有一些我缺少的东西会使这项工作?

4 个答案:

答案 0 :(得分:14)

以下步骤可用于解决您提到的问题。

将设备安装为USB海量存储的过程不一致 跨设备和制造商特定。当您通过USB线将设备连接到桌面时,某些设备(如Nexus S)会提供“打开USB存储设备”。其他设备(如Galaxy S3)现在需要一个应用程序才能将设备作为大容量存储启动。无论哪种方式,Android设备通常都提供此类功能,您必须创建一个与您设备的制造商规格相匹配的文件。

在使用USB主机API之前,您需要添加到应用程序的清单文件中:

  • 由于并非所有Android设备都支持USB主机API,因此请包含一个声明您的应用程序使用android.hardware.usb.host功能的元素。
  • 如果您希望通知您的应用程序连接的USB设备,请在主要活动中为android.hardware.usb.action.USB_DEVICE_ATTACHED意图指定一个和元素对。

将USB_DEVICE_ATTACHED添加到您的manisfest文件中:

<manifest ...>
    <uses-feature android:name="android.hardware.usb.host" />
    <uses-sdk android:minSdkVersion="12" />
    ...
    <application>
        <activity ...>
            ...
            <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" />
        </activity>
    </application>
</manifest>

为了帮助您的APP发现特定的USB设备,您可以使用意图过滤器:

<activity ...>
    ...
    <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" />
</activity>

您还必须指定您的设备和供应商ID:

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <usb-device vendor-id="1234" product-id="5678" />
</resources>

这应该足以处理您的USB host连接。现在拨打USB:

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

使用描述符打开与usb device的连接 - 例如:

UsbManager myUsbManager = (UsbManager) 
getSystemService(Context.USB_SERVICE);
UsbAccessory myUsbAccessory = (myUsbManager.getAccessoryList())[0];
ParcelFileDescriptor pfd = myUsbManager.openAccessory(myUsbAccessory);
FileDescriptor fileDescriptor = pfd.getFileDescriptor();
FileInputStream myFileInputStream = new FileInputStream(fileDescriptor);
FileOutputStream myFileOutputStream = new FileOutputStream(fileDescriptor);

如果您仍然遇到SELinux级别的问题,可以使用一些编辑来使您的程序顺利运行:

// default.prop
ro.secure=1              -----------------> ro.secure=0
ro.adb.secure=1        -----------------> ro.adb.secure=0

//init.rc
setsebool debugfs 1   --------> setsebool debugfs 0
setenforce 0
setprop selinux.reload_policy 1  ------->  setprop selinux.reload_policy 0

// init.target.rc
setprop selinux.reload_policy 1   ----->  setprop selinux.reload_policy 0

默认情况下,SELinux设置为强制实施最高安全性,并且您希望通过USB授予客户端对Android设备的访问权限。

enter image description here

根据您的Android品牌和型号,尝试拔下连接设备和桌面的USB电缆,然后重新插入。系统会提示您“打开USB”存储空间。如果是这种情况,请继续尝试浏览Android上的设置→更多... ,然后查找USB海量存储选项。

http://www.pocketables.com/images/old/6a00d83451c9ec69e201675f40c44a970b-500wi.png

或者查看设备制造商推荐的USB海量存储过程。当你打开USB存储设备时,设备让你知道有些应用程序会停止,然后就可以了。现在转到桌面计算机并浏览到USB大容量存储介质,如果没有重命名,通常称为NO NAME。单击您的大容量存储设备,然后在脚文件夹中找到名为data.tsv。

的文件

enter image description here

您也可以通过在您喜欢的文本编辑器中打开data.tsv来检查它。你会发现两个柱子整齐地分开了一个标签;在每一行中,您将找到一对整数值。这对我们的项目来说已经足够了。更复杂的数据项目通常需要每行的唯一标识符,一个表中的一行指向另一个表中的特定记录。

enter image description here

根据您的development environment,您还必须相应地调整您的设置。如果您在Windows上进行开发,请按照USB驱动程序安装instructions available进行操作。如果您在Linux上进行开发,请按照setting up您的设备进行开发的说明进行操作。

enter image description here

此外,还值得一提的是,许多以前发布的Android设备只能作为USB设备使用,无法启动与外部USB设备的连接。 Android开放附件(AOA)支持克服了此限制,允许您通过允许附件启动connection来构建可与各种Android设备交互的附件。在项目中可以找到常见的Android Open Accessory示例:使用USB host mode录制和播放音频 - 这当然需要USB模式启动并运行。

enter image description here

让Android通过USB与Arduino微控制器进行通信也是一种最近变得非常成功的实现方式,因为它允许您扩展Android功能,通过多设备解决方案方法集成其他功能。允许设备与Android USB通信的典型Arduino Sketch将如下所示:

// the USB Host libraries
#include <Max3421e.h>
#include <Usb.h>
// the AOA library
#include <AndroidAccessory.h>

void setup();
void loop();

void setup()
{   // start serial debugging
    Serial.begin(115200);
    Serial.print("\r\nADK has run setup().");
    Serial.println("Ready to start USB communication...");
}

void loop()
{   // example - read the voltage from a sensor
    uint16_t val;
    val = analogRead(TEMP_SENSOR); // or any sort of input
    Serial.println(val,HEX);
    Serial.write(val);
    // Delay for 100 milliseconds.
    delay(100);
}

所有Arduino项目都必须声明setup()和loop()方法,否则您的Android将无法正常通信。

还要记住使用AOA所需的最低要求列表:

  • 兼容AOA的Android设备。要在尝试此示例之前测试兼容性,请参阅“支持的Android设备”部分,以获取Google Play上提供的Microchip AOA演示应用程序的链接。
  • 兼容的微控制器板。如果您不确定,Arduino Mega ADK将是一个简单的选择。

enter image description here

使用USB的Android设备的可能性令人惊叹,对能够充分利用这些功能的创新APP的需求将会显着增长。

答案 1 :(得分:1)

您的错误与权限无关,与I / O相关,-1错误相当于

LIBUSB_ERROR_IO - Input/output error. 

您可以修改JNI interface以将libusb置于调用模式中调用libusb_set_debug(),我认为这是了解实际情况的唯一方法。

无论如何,首先检查VID / PID以确保它位于已连接设备列表中。

答案 2 :(得分:0)

在Android上,你不能在没有root的情况下使用libusb_open_device_with_vid_pid。 要访问USB设备,您必须使用UsbDeviceManager Android API。

我知道将libusb连接到没有root的Android的公共源代码的唯一示例是:https://github.com/martinmarinov/rtl_tcp_andro-/

您将无法获得/ dev / bus / usb / xxx / yyy的读/写访问权限。 Android的方法是,系统服务通过binder在您要求的特定/ dev / bus / usb / xxx / yyy设备上发送已经打开的文件描述符。

关于如何在Android中使用java处理UsbHost已经有很多文档,所以我会指出之后剩下的内容。

  • 你需要一个修补的libusb(rtl_tcp_andro-中的那个),它可以采用filedescriptor而不是设备名称/ pid / vid
  • 您需要使用UsbDeviceConnection.getFileDescriptor()
  • 检索的fd调用libusb_open2(这是如何在rtl_tcp_andro的libusb中调用fd的新函数)

编辑:我看到rtl_tcp_andro-还添加了一个libusb_init2,我不明白为什么是ATM,但提交说这是L支持,所以我猜它也是需要的。

答案 3 :(得分:0)

有问题的usb补丁以下一种方式工作:

  1. 你必须通过UsbManager打开设备
  2. 由libusb打开
  3. close by libusb
  4. 由UsbManager关闭
  5. 确切的顺序将起作用。