Trabajar con dispositivos LibUsb desde Android

Un día, necesitaba un dispositivo que se controlara a través de USB desde un programa de escritorio para que también se controlara a través de una aplicación de Android. La peculiaridad era que HID, CDC y otras clases de dispositivos estándar no se usaban. La transferencia de datos se realizó mediante transferencia masiva y puntos finales. La base de trabajar con usb fue la biblioteca libusb.

Crearemos una aplicación de prueba con la cual será posible transferir y recibir datos arbitrarios del dispositivo.

Tocaré puntos clave, y el enlace al código completo estará al final.

Para empezar, actuamos de acuerdo con la documentación oficial para trabajar con UsbHost.
Agregar una línea al manifiesto

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

Si queremos que el dispositivo se detecte automáticamente y la aplicación se inicie, en el manifiesto de la actividad principal escribimos lo siguiente.

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

Especifique para nuestro dispositivo su VID y PID en el archivo con recursos device_filter.xml

 <resources> <usb-device product-id="0037" vendor-id="8742"/> </resources> 

Obtenemos el administrador usb en el método onCreate.

 mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); 

A continuación, obtenemos una lista de dispositivos conectados a USB, y entre ellos estamos buscando un dispositivo de la clase USB_CLASS_PER_INTERFACE que necesitamos.

 UsbDevice findDevice(UsbManager usbManager) { for (UsbDevice usbDevice : usbManager.getDeviceList().values()) { if (usbDevice.getDeviceClass() == UsbConstants.USB_CLASS_PER_INTERFACE) { return usbDevice; } else { UsbInterface usbInterface = findInterface(usbDevice); if (usbInterface != null) return usbDevice; } } return null; } UsbInterface findInterface(UsbDevice usbDevice) { for (int nIf = 0; nIf < usbDevice.getInterfaceCount(); nIf++) { UsbInterface usbInterface = usbDevice.getInterface(nIf); if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_PER_INTERFACE) { return usbInterface; } } return null; } 

A continuación, encontramos la interfaz que necesitamos, no olvide verificar los permisos, iterar sobre todos sus puntos de control, entre ellos seleccionamos los puntos de lectura y escritura, y finalmente nos conectamos.

 private void initUsbDevice() { PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter); mUsbManager.requestPermission(mUsbDevice, mPermissionIntent); mUsbInterface = findInterface(mUsbDevice); for (int nEp = 0; nEp < mUsbInterface.getEndpointCount(); nEp++) { UsbEndpoint tmpEndpoint = mUsbInterface.getEndpoint(nEp); if (tmpEndpoint.getType() != UsbConstants.USB_ENDPOINT_XFER_BULK) continue; if ((mOutEndpoint == null) && (tmpEndpoint.getDirection() == UsbConstants.USB_DIR_OUT)) { mOutEndpoint = tmpEndpoint; } else if ((mInEndpoint == null) && (tmpEndpoint.getDirection() == UsbConstants.USB_DIR_IN)) { mInEndpoint = tmpEndpoint; } } if (mOutEndpoint == null) { Toast.makeText(this, "no endpoints", Toast.LENGTH_LONG).show(); } mConnection = mUsbManager.openDevice(mUsbDevice); if (mConnection == null) { Toast.makeText(this, "can't open device", Toast.LENGTH_SHORT).show(); return; } mConnection.claimInterface(mUsbInterface, true); startIoManager(); } 

Para trabajar con E / S, almacenamiento en búfer de datos, asincronía y otras cosas convenientes, se usa una clase de administrador auxiliar, pero en esencia, el intercambio de datos se reduce al siguiente código.

Lectura:

 mConnection.bulkTransfer(mInEndpoint, data, size, READ_TIMEOUT); 

Registro:

 int bytesWritten = mConnection.bulkTransfer(mOutEndpoint, Arrays.copyOfRange(data, offset, offset + size), size, WRITE_TIMEOUT); 

De esta manera, los paquetes BulkTransfer se transmiten y reciben.

Como resultado, nuestra sencilla aplicación puede transmitir y recibir datos arbitrarios.





Funciona!

El proyecto de esta aplicación de prueba en GitHub

Enlaces utiles:

  1. Biblioteca para trabajar con FT232 y otros dispositivos CDC en Android.
  2. La documentación oficial de Android para trabajar con UsbHost.

Source: https://habr.com/ru/post/es426697/


All Articles