java android android-ndk jni libusb-1.0

java - libusb_open_device_with_vid_pid falló al intentar acceder al dispositivo USB



android android-ndk (4)

Estoy intentando que un dispositivo USB se conecte a un dispositivo Android 5.1.1. Anteriormente había estado usando libusb regular para KitKat, pero Lollipop ha aumentado la seguridad y esto ya no funciona.

Esto está bien documentado, requiriendo root para establecer el nivel de SELinux. No quiero tener que rootear el dispositivo para que el dispositivo USB se conecte a él.

Después de mirar alrededor, encontré esta respuesta y probé esta bifurcación de libusb , pero ahora estoy recibiendo un nuevo error.

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

No he cambiado ninguno de los códigos, solo la biblioteca.

¿Sigue siendo un problema de permiso, o hay algo que estoy perdiendo que hará que esto funcione?


En Android, no puedes usar libusb_open_device_with_vid_pid sin root. Para obtener acceso a un dispositivo USB, debe usar la API de Android UsbDeviceManager.

El único ejemplo que conozco del código fuente público que conecta libusb a Android sin root es: https://github.com/martinmarinov/rtl_tcp_andro-/

Nunca obtendrá acceso de lectura / escritura a / dev / bus / usb / xxx / yyy. La forma de hacerlo de Android es que los servicios del sistema le envíen, a través de la carpeta, un descriptor de archivo ya abierto en el dispositivo específico / dev / bus / usb / xxx / yyy que solicitó.

Ya hay muchas documentaciones sobre cómo manejar UsbHost desde Java en Android, así que señalaré lo que queda después de eso.

  • Necesita un libusb parcheado (el que está en rtl_tcp_andro- va a hacer), que puede tomar un descriptor de archivo en lugar de un nombre de dispositivo / pid / vid
  • Debe llamar a libusb_open2 (así es como se llama a esta nueva función con fd en el libusb de rtl_tcp_andro) con el fd que obtendrá con UsbDeviceConnection.getFileDescriptor ()

Edit: veo que rtl_tcp_andro- también agregó libusb_init2, no entiendo por qué ATM, pero el compromiso dice que es para el soporte de L, así que supongo que también es necesario.


Ese parche usb mencionado en la pregunta funciona de la siguiente manera:

  1. DEBES abrir el dispositivo por UsbManager
  2. abierto por libusb
  3. cerca de libusb
  4. cerca de UsbManager

exactamente esa orden funcionará


Los siguientes pasos pueden usarse para resolver los problemas que mencionó.

El proceso de montaje del dispositivo como almacenamiento masivo USB es inconsistente en todos los dispositivos y es específico del fabricante. Algunos dispositivos como el Nexus S ofrecen "Activar el almacenamiento USB" cuando conecta el dispositivo al escritorio mediante un cable USB. Otros dispositivos como el Galaxy S3 requieren una aplicación ahora para iniciar el dispositivo como almacenamiento masivo. De cualquier manera, los dispositivos Android generalmente ofrecen esta característica, y tendrás que crear un archivo que coincida con las especificaciones del fabricante de tu dispositivo.

Debe agregar al archivo de manifiesto de su aplicación antes de trabajar con las API de host USB:

  • Debido a que no se garantiza que todos los dispositivos con Android sean compatibles con las API de host USB, incluya un elemento que declare que su aplicación utiliza la función android.hardware.usb.host.
  • Si desea que su aplicación sea notificada de un dispositivo USB conectado, especifique un par de elementos y para la intención de android.hardware.usb.action.USB_DEVICE_ATTACHED en su actividad principal.

Agregue USB_DEVICE_ATTACHED a su archivo 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>

Para ayudar a su aplicación a descubrir un dispositivo USB en particular, puede usar el filtro de intención:

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

También debe especificar su dispositivo y la identificación del proveedor:

<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="1234" product-id="5678" /> </resources>

Esto debería ser suficiente para lidiar con su conexión de host USB . Ahora llama USB:

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

Use el descriptor para abrir la conexión al dispositivo usb , por ejemplo:

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

Si aún tiene problemas con el nivel de SELinux, aquí tiene algunas ediciones que puede utilizar para que su programa se ejecute sin problemas:

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

Como SELinux está configurado de manera predeterminada para garantizar la seguridad más alta, y usted quiere otorgarle a un cliente acceso a su dispositivo Android a través de USB.

Dependiendo de su marca y modelo de Android, intente desconectar el cable USB que conecta su dispositivo y el escritorio y vuelva a enchufarlo. Se le solicitará que "active el almacenamiento USB". Si este es el caso, siga adelante e intente navegar a Configuración → Más ... en el Android y busque una opción de almacenamiento masivo USB.

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

También puede buscar el proceso de almacenamiento masivo USB recomendado por el fabricante de su dispositivo. Cuando enciende el almacenamiento USB, el dispositivo le avisa que algunas aplicaciones se detendrán, adelante y OK. Ahora muévase a su computadora de escritorio y busque su medio de almacenamiento masivo USB, a menudo llamado SIN NOMBRE si no le ha cambiado el nombre. Haga clic en su dispositivo de almacenamiento masivo y, allí mismo, en la carpeta de pie, busque un archivo llamado data.tsv.

También puede verificar data.tsv abriéndolo en su editor de texto favorito. Encontrarás dos columnas separadas por una pestaña; en cada fila, encontrarás un par de valores enteros. Esto es perfectamente suficiente para nuestro proyecto. Los proyectos de datos más complejos generalmente requieren un identificador único para cada fila, una fila en una tabla para apuntar a un registro específico en otra.

De acuerdo con su entorno de desarrollo , también tiene que ajustar sus configuraciones en consecuencia. Si está desarrollando en Windows, siga las instrucciones de instalación del controlador USB disponibles . Si está desarrollando en Linux, siga las instrucciones para configurar su dispositivo para el desarrollo.

Además, vale la pena mencionar que muchos dispositivos Android lanzados anteriormente solo son capaces de actuar como dispositivos USB y no pueden iniciar conexiones con dispositivos USB externos. La compatibilidad con Android Open Accessory (AOA) supera esta limitación y le permite construir accesorios que pueden interactuar con una variedad de dispositivos con Android, al permitir que el accesorio inicie la connection . En el proyecto se puede encontrar un ejemplo de uso común de Android Open Accessory: grabar y reproducir audio usando el modo de host USB , que por supuesto requiere que el modo USB esté en funcionamiento.

Hacer que Android se comunique a través de USB con los microcontroladores Arduino también es un tipo de implementación que demostró ser muy exitosa más recientemente, ya que le permite ampliar sus capacidades de Android integrando características adicionales a través de un enfoque de solución de múltiples dispositivos. Un Arduino Sketch típico para permitir que la comunicación del dispositivo con tu Android USB se vea así:

// 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); }

Todos los proyectos de Arduino deben tener un método setup () y un método loop () declarados, de lo contrario, su Android no se comunicará correctamente.

También recuerde que una lista de requisitos mínimos necesarios para usar AOA:

  • Un dispositivo Android compatible con AOA. Para probar la compatibilidad antes de probar este ejemplo, consulte la sección "Dispositivos Android compatibles" para ver los enlaces a las aplicaciones de demostración de Microchip AOA disponibles en Google Play.
  • Una placa de microcontrolador compatible. El Arduino Mega ADK sería una opción fácil si no está seguro.

Las posibilidades de que los dispositivos Android usen USB son increíbles, y la demanda de aplicaciones innovadoras que sean capaces de aprovechar al máximo estas características crecerá notablemente.


Su error no está relacionado con los permisos relacionados con la E / S, el error -1 es equivalente a

LIBUSB_ERROR_IO - Input/output error.

Puede modificar la interfaz JNI para poner libusb en modo de depuración llamando a libusb_set_debug() , creo que esa es la única forma de saber qué está sucediendo realmente.

De todos modos, primero verifique su VID / PID para asegurarse de que esté en la lista de dispositivos conectados.