[LINUX] USB-Geräteprogrammierung mit nativem C unter Android 5.0 und höher

Ich möchte USB-Geräte mit C-Bibliothek auf Android Lolipop oder höher verarbeiten

Seit Lolipop basieren Android-Geräte auf SELinux, daher ist es etwas schwierig, mit Permission umzugehen. In diesem Artikel werden die Punkte beschrieben, die beim Verwenden / Schreiben einer Bibliothek in C-Sprache zu beachten sind, die USB-Geräte auf einem Android-Terminal als USB-Host verarbeitet.

Warum C-Sprache?

Traditionell sind die Schichten, die näher an den Gerätetreibern liegen, meist in C geschriebene Bibliotheken. Da Android ein Derivat von Linux ist, ist es dasselbe, da es USBFS für USB-Treiber verarbeitet, und im Grunde können Sie Bibliotheken verwenden, die sich auf Linux-USB-Geräte beziehen. Mit der einzigartigen USB-Bibliothek von Android müssen Räder nicht neu erfunden werden.

Einschränkungen in C.

Beispielsweise ist libusb eine C-Bibliothek, die USB-Geräte unter Android verarbeitet, aber libusbs [README](https: // github). Wenn Sie sich com / libusb / libusb / blob / master / android / README ansehen, sehen Sie Folgendes.

The default system configuration on most Android device will not allow access to USB devices. There are several options for changing this.

If you have control of the system image then you can modify the ueventd.rc used in the image to change the permissions on /dev/bus/usb//. If using this approach then it is advisable to create a new Android permission to protect access to these files. It is not advisable to give all applications read and write permissions to these files.

For rooted devices the code using libusb could be executed as root using the "su" command. An alternative would be to use the "su" command to change the permissions on the appropriate /dev/bus/usb/ files.

Users have reported success in using android.hardware.usb.UsbManager to request permission to use the UsbDevice and then opening the device. The difficulties in this method is that there is no guarantee that it will continue to work in the future Android versions, it requires invoking Java APIs and running code to match each android.hardware.usb.UsbDevice to a libusb_device.

In der Tat beschränkt SELinux den Zugriff unter "/ dev / bus / usb /", so dass der Ansatz geschrieben ist, dass Sie Ihr Bestes geben sollten, indem Sie selbst die Erlaubnis geben. Dies ist korrekt, wenn es als Android als SELinux betrachtet wird, aber es ist für die Mehrheit der Android-App-Entwickler, die ohne Root-Rechte entwickeln müssen, unscharf. Natürlich sind diese Informationen allein schwer zu lösen.

Prozedur mit libusb etc.

Normalerweise sieht das Programm bei Verwendung der C-Bibliothek wie folgt aus.

  1. Öffnen Sie den Port und rufen Sie den Dateideskriptor ab.
  2. Laden Sie den USB-Deskriptor des Geräts mit dem Dateidrucker. (Referenz: SyncHack-USB / Descriptor)
  3. Identifizieren Sie die USB-Schnittstelle oder den USB-Endpunkt über den USB-Deskriptor und kommunizieren Sie mit dem Gerät.

usb.c


const char* port_name = "/dev/bus/usb/000/001"; //USB Gerät(Es ändert sich jedes Mal, wenn Sie eine Verbindung herstellen, also suchen Sie tatsächlich usw.)
int fd; //Datei-Disk-Drucker
int rc;
int n_read;
byte[] desc; //Speicherort des USB-Deskriptors

fd = open(port_name, 0_RDWR); //Port öffnen
...
rc = read(fd, desc, n_read); //Erstes Laden des USB-Deskriptors
...

Probleme mit diesen Code-Berechtigungen

Dieser Code kann problemlos auf Android-Geräten verwendet werden, wenn er mit Root-Rechten ausgeführt oder das Gerät angepasst werden kann. Auf einem Nicht-Root-Terminal verursacht das Öffnen eines Ports jedoch einen Berechtigungsfehler und funktioniert nicht. Was sollen wir dann tun?

Problemumgehung

Wenn Sie die Schritte ausführen, um auf ein USB-Gerät im Android SDK zuzugreifen, können Sie die Berechtigung für dieses Gerät ordnungsgemäß erhalten. Informationen zum normalen Zugriff auf ein USB-Gerät im Android SDK finden Sie im USB Host of Developer Guide. Wenn Sie das bestimmte Verfahren befolgen, können Sie es problemlos erhalten. Wenn Sie die C-Bibliothek nicht verwenden, UsbManager, [ UsbDevice](https: // Entwickler. android.com/reference/android/hardware/usb/UsbDevice.html), UsbDeviceConnection Geh einfach. Selbst wenn beispielsweise die obige "usb.c" nach dem Ausführen von "USBManager # openDevice ()" ausgeführt wird, tritt ein Fehler auf. Dies liegt daran, dass im SDK tatsächlich ein Dateidrucker ausgegeben wird, wenn "openDevice ()" ausgeführt wird, und der Zugriff nur über diesen zulässig ist. Es ist nicht gestattet, einen neuen zu öffnen, und es muss nur der Dateidrucker verwendet werden. Der Dateideskriptor kann mit UsbDeviceConnection # getFileDescpritor () abgerufen werden. Es gibt auch einen libusb-Zweig, der diese "Wiederverwendung von Dateideskriptoren" unterstützt. Erhalten von der SDK-Welt als Argument der Funktion op_open2 () wie unten gezeigt. Es wurde entwickelt, um einen Dateideskriptor anzugeben.

static int op_open2(struct libusb_device_handle *handle, int fd)

Weitere Probleme-USB Descpritor

Selbst wenn Sie den Dateidrucker wiederverwenden, tritt jetzt ein anderes Problem auf. Das heißt, E / A-Fehler beim Lesen von USB Descpritor. Tatsächlich liest das SDK den USB-Descpritor gleichzeitig mit "USBManager # openDevice ()". Wenn Sie also das Preta der Dateidiskette wiederverwenden, wurde es bereits gelesen und Sie können es nicht mit Ihrem eigenen Code lesen. Wohin ging der geladene USB-Deskriptor? USBDeviceConnection # getRawDescpritors () Es kann mit herausgenommen werden.

Vollständiges Formular

Es wurde also bestätigt, dass, wenn die C-Bibliothek des USB-Geräts durch das folgende Verfahren verwendet wird, die vorhandene Bibliothek verwendet werden kann, während das Problem der Berechtigung und das Problem des USB-Descpritors vermieden werden.

Usb.java


UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();  
for(UsbDevice device : deviceList.values()) {
  if(device.getVenforId() == 0xZZ && device.getProductId() == 0xYY) { //Bei der Steuerung nach Produktspezifikation
    UsbDeviceConnection connection = manager.openDevice(device); //An dieser Stelle öffnen(), read()Wird ausgeführt.
    int fd = connection.getFileDescptitor(); //Vom SDK zugelassene kommunizierbare Datenträgerdrucker
    byte[] descpritors = connection.getRawDescpritors(); //Device, Configuration, Interface,Beinhaltet alle Descpritoren wie Endpoint
    callJNIUsbLib(fd, descpritors); //Sie kann verarbeitet werden, indem diese beiden Informationen an die JNI-Seite übergeben werden.
  }
}

Auf der Seite der C-Bibliothek sollte die Implementierung lauten: "Verwenden Sie die Datei-Datenträger-Preta, anstatt die Datei zu öffnen" und "Verwenden Sie die übergebene Datei, ohne den USB-Descpritor zu erwerben".

Recommended Posts

USB-Geräteprogrammierung mit nativem C unter Android 5.0 und höher
Erstellen Sie Discord Bot und führen Sie es auf einem Android-Gerät aus
Programmieren mit Python und Tkinter
Lösen mit Ruby und Python AtCoder ABC011 C Dynamische Planungsmethode
X86 Assembler unter Linux (Verknüpfung mit C)
Ein Memo mit Python2.7 und Python3 in CentOS
[C] [Python] Lesen mit AquesTalk unter Linux
Normal programmieren mit Node-RED-Programmierung mit Raspberry Pi 3
Teilen Sie VLC-Wiedergabelisten auf PC und Android
RaspberryPi L Chika mit Python und C #