Eines Tages brauchte ich ein Gerät, das über USB von einem Desktop-Programm aus gesteuert wurde, um auch über eine Android-Anwendung gesteuert zu werden. Die Besonderheit war, dass HID, CDC und andere Standardgeräteklassen nicht verwendet wurden. Die Datenübertragung erfolgte über Massenübertragung und Endpunkte. Die Basis für die Arbeit mit USB war die libusb-Bibliothek.
Wir werden eine Testanwendung erstellen, mit der beliebige Daten vom Gerät übertragen und empfangen werden können.
Ich werde auf wichtige Punkte eingehen, und der Link zum vollständigen Code wird am Ende sein.
Zunächst handeln wir gemäß der offiziellen Dokumentation für die Arbeit mit UsbHost.
Fügen Sie dem Manifest eine Zeile hinzu
<uses-feature android:name="android.hardware.usb.host"/>
Wenn das Gerät automatisch erkannt und die Anwendung gestartet werden soll, schreiben wir im Manifest für die Hauptaktivität Folgendes.
<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"/>
Geben Sie für unser Gerät die VID und PID in der Datei mit den Ressourcen device_filter.xml an
<resources> <usb-device product-id="0037" vendor-id="8742"/> </resources>
Wir erhalten den USB-Manager in der onCreate-Methode.
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE)
Als nächstes erhalten wir eine Liste der an USB angeschlossenen Geräte, und unter diesen suchen wir nach einem Gerät der Klasse USB_CLASS_PER_INTERFACE, das wir benötigen.
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; }
Als nächstes finden wir die Schnittstelle, die wir benötigen. Vergessen Sie nicht, die Berechtigungen zu überprüfen. Wir sortieren alle Kontrollpunkte, wählen die Lese- und Schreibpunkte aus und stellen schließlich eine Verbindung her.
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(); }
Um mit E / A, Datenpufferung, Asynchronität und anderen praktischen Dingen zu arbeiten, wird eine Hilfsmanagerklasse verwendet, aber im Wesentlichen wird der Datenaustausch auf den folgenden Code reduziert.
Lesen:
mConnection.bulkTransfer(mInEndpoint, data, size, READ_TIMEOUT);
Aufzeichnung:
int bytesWritten = mConnection.bulkTransfer(mOutEndpoint, Arrays.copyOfRange(data, offset, offset + size), size, WRITE_TIMEOUT);
Auf diese Weise werden BulkTransfer-Pakete gesendet und empfangen.
Dadurch kann unsere einfache Anwendung beliebige Daten senden und empfangen.


Es funktioniert!
Das Projekt dieser
Testanwendung auf GitHubNützliche Links:
- Bibliothek für die Arbeit mit FT232 und anderen CDC-Geräten unter Android.
- Die offizielle Android-Dokumentation für die Arbeit mit UsbHost.