尝试访问 USB 设备时libusb_open_device_with_vid_pid失败

我正在尝试获取 USB 设备以连接到 Android 5.1.1 设备。以前,我一直在使用KitKat的常规libusb,但是棒棒糖提高了安全性,这不再有效。

这是有据可查的,需要 root 来设置 SELinux 级别。我不想让USB设备连接到它。

环顾四周,我遇到了这个答案,我已经尝试了这个libusb分叉,但是现在我得到了一个新的错误

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

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

这是否仍然是一个权限问题,或者我缺少什么可以使这项工作?


答案 1

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

将设备装载为 USB 大容量存储的过程在各个设备和特定于制造商时不一致。某些设备(如Nexus S)在通过USB电缆将设备连接到桌面时提供“打开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主机连接。现在调用 USB:

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

使用描述符打开与 USB 设备的连接 - 例如:

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大容量存储选项。

enter image description here
(资料来源:pocketables.com

或者,查找设备制造商推荐的 USB 大容量存储过程。当您打开 USB存储 ,设备让您知道某些应用程序将停止,请继续并确定。现在移动到台式计算机并浏览到USB大容量存储介质,如果您尚未重命名,则通常称为NO NAME。单击您的大容量存储设备,然后在脚文件夹中找到一个名为data.tsv的文件。

enter image description here

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

enter image description here

根据您的开发环境,您还必须相应地调整设置。如果您在 Windows 上进行开发,请按照可用的 USB 驱动程序安装说明进行操作。如果在 Linux 上进行开发,请按照设置设备以进行开发的说明进行操作。

enter image description here

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

enter image description here

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

// 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()和一个look()方法,否则你的Android将无法正确通信。

另请记住,使用AOA所需的最低要求列表:

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

enter image description here

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


答案 2

你的错误与权限无关,与I/O有关,错误等效于-1

LIBUSB_ERROR_IO - Input/output error. 

你可以修改JNI接口,把libusb放在调试模式调用,我认为这是知道到底发生了什么的唯一方法。libusb_set_debug()

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


推荐