Подтвердить что ты не робот

Ошибка libusb_open_device_with_vid_pid при попытке доступа к USB-устройству

Я пытаюсь подключить устройство USB к устройству Android 5.1.1. Раньше я использовал обычный libusb для KitKat, но у Lollipop повышенная безопасность, и это больше не работает.

Это хорошо документировано, требуя от root установить уровень SELinux. Я не хочу запускать устройство, чтобы подключить USB-устройство к нему.

Оглядевшись, я наткнулся на этот ответ, и я пробовал этот libusb fork, однако теперь я получаю новую ошибку

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

Я не изменил ни одного кода, только библиотека.

Является ли это еще проблемой разрешения, или есть что-то, что мне не хватает, что сделает эту работу?

4b9b3361

Ответ 1

Следующие шаги могут быть использованы для решения упомянутых вами проблем.

Процесс монтирования устройства в качестве запоминающего устройства USB несовместим через устройства и в зависимости от производителя. Некоторые устройства, такие как Nexus S, предлагают "Включить USB-накопитель" при подключении устройства к рабочему столу через USB-кабель. Другие устройства, такие как Galaxy S3, требуют приложения для запуска устройства в качестве запоминающего устройства. В любом случае, устройства Android обычно предлагают такую функцию, и вам придется создать файл, который соответствует спецификации производителя вашего устройства.

Перед работой с API-интерфейсами хоста USB необходимо добавить в файл манифеста приложения:

  • Поскольку не все устройства на базе Android гарантированно поддерживают API-интерфейсы USB-хоста, включите элемент, который объявляет, что ваше приложение использует функцию android.hardware.usb.host.
  • Если вы хотите, чтобы ваше приложение уведомлялось о подключенном USB-устройстве, укажите пару элементов и для намерения android.hardware.usb.action.USB_DEVICE_ATTACHED в вашей основной деятельности.

Добавьте USB_DEVICE_ATTACHED в файл манифеста:

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

Чтобы помочь вашему приложению обнаружить определенное 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>

Вы также должны указать свое устройство и идентификатор поставщика:

<?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 по умолчанию настроен на обеспечение максимальной безопасности, и вы хотите предоставить клиентский доступ к вашему устройству Android через USB.

enter image description here

В зависимости от марки и модели Android попробуйте отключить USB-кабель, соединяющий ваше устройство и настольный компьютер, и снова подключить его. Вам будет предложено "Включить USB-накопитель". Если дело обстоит именно так, попробуйте перейти в "Настройки" → "Дополнительно" на Android и найти вариант USB-накопителя.

enter image description here
(источник: pocketables.com)

В качестве альтернативы обратите внимание на процесс запоминающего устройства USB, рекомендованный производителем вашего устройства. Когда вы включаете USB-накопитель, устройство сообщает, что некоторые приложения будут остановлены, продолжайте и подтвердите это. Теперь перейдите к настольному компьютеру и перейдите к USB-накопителю, который часто называется NO NAME, если вы его не переименовали. Нажмите на свое устройство хранения данных и прямо там, в папке foot, найдите файл с именем data.tsv.

enter image description here

Вы также можете проверить data.tsv, открыв его в своем любимом текстовом редакторе. Вы найдете две колонки, аккуратно разделенные вкладкой; в каждой строке вы найдете пару целочисленных значений. Этого вполне достаточно для нашего проекта. Для более сложных проектов данных обычно требуется уникальный идентификатор для каждой строки, строка в одной таблице, указывающая на конкретную запись в другой.

enter image description here

В соответствии с вашей средой разработки, вам также необходимо соответствующим образом настроить параметры. Если вы разрабатываете в Windows, следуйте инструкциям по установке драйвера USB. Если вы разрабатываете для Linux, следуйте инструкциям по настройке устройства для разработки.

enter image description here

Кроме того, также стоит упомянуть, что многие ранее выпущенные устройства на платформе Android способны работать только как USB-устройства и не могут устанавливать соединения с внешними USB-устройствами. Поддержка Android Open Accessory (AOA) преодолевает это ограничение и позволяет создавать аксессуары, которые могут взаимодействовать с целым рядом устройств на платформе Android, позволяя аксессуару инициировать соединение. Пример общего использования Android Open Accessory можно найти в проекте: записывать и воспроизводить аудио, используя USB-хост-режим - что, конечно, требует, чтобы USB-режим был включен и работал.

enter image description here

Использование Android для связи через USB с микроконтроллерами Arduino также является одним из видов реализации, который за последнее время оказался очень успешным, поскольку он позволяет расширять возможности Android за счет интеграции дополнительных функций с помощью подхода с несколькими устройствами. Типичный эскиз Arduino, позволяющий устройству взаимодействовать с 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() и loop(), иначе ваш Android не будет взаимодействовать должным образом.

Также помните, что список минимальных требований, необходимых для использования AOA:

  • AOA-совместимое устройство Android. Чтобы проверить совместимость, прежде чем пытаться использовать этот пример, обратитесь к разделу "Поддерживаемые устройства Android", где приведены ссылки на демонстрационные приложения Microchip AOA, доступные в Google Play.
  • Совместимая плата микроконтроллера. Arduino Mega ADK будет простым вариантом, если вы не уверены.

enter image description here

Возможности устройств Android, использующих USB, поразительны, и спрос на инновационные приложения, способные в полной мере использовать такие функции, значительно возрастет.

Ответ 2

Ваша ошибка не связана с разрешениями, связанными с I/O, ошибка -1 эквивалентна

LIBUSB_ERROR_IO - Input/output error. 

Вы можете модифицировать JNI-интерфейс, чтобы поместить libusb в режим отладки, вызвав libusb_set_debug(), я думаю, что это единственный и единственный способ узнать что на самом деле происходит.

В любом случае, сначала проверьте VID/PID, чтобы убедиться, что он находится в списке подключенных устройств.

Ответ 3

В Android вы не можете использовать libusb_open_device_with_vid_pid без root. Чтобы получить доступ к USB-устройству, вы должны использовать API Android UsbDeviceManager.

Единственный пример, который я знаю об общедоступном исходном коде, соединяющем libusb с Android без root: https://github.com/martinmarinov/rtl_tcp_andro-/

Вы никогда не получите доступ для чтения/записи к /dev/bus/usb/xxx/yyy. Android, это системные службы, которые вы отправляете через связующее, уже открытый файловый дескриптор на конкретном устройстве /dev/bus/usb/xxx/yyy, которое вы просили.

Уже есть много документов о том, как обращаться с UsbHost с java на Android, поэтому я укажу на то, что осталось после этого.

  • Вам нужен исправленный libusb (тот, который находится в файле rtl_tcp_andro-), который может принимать файл filedescriptor вместо имени устройства /pid/vid
  • Вам нужно вызвать libusb_open2 (как эта новая функция с fd вызывается в rtl_tcp_andro libusb) с помощью fd, которую вы получите с помощью UsbDeviceConnection.getFileDescriptor()

Изменить: я вижу rtl_tcp_andro- также добавил libusb_init2, я не понимаю, почему ATM, но фиксация говорит об этом для поддержки L, поэтому я думаю, что это также необходимо.

Ответ 4

Этот патч usb, упомянутый в вопросе, работает следующим образом:

  • ВЫ ДОЛЖНЫ открывать устройство с помощью UsbManager
  • открыть libusb
  • закрыть libusb
  • закрыть с помощью UsbManager

точно этот порядок будет работать.