Bytes direkt an ein Usb-Device senden mit Java

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,

    vor einiger Zeit stand ich vor der Aufgabe, Bondrucker zu bedienen, die an einem USB-Port des Raspi angeschlossen werden sollten. Wenn man den Zugriff über Drucker-Treiber vermeiden möchte (oder muss aufgrund fehlender Treiber), ist es notwendig, direkt auf die USB-Ports zu schreiben. Ich möchte hiermit mein Wissen teilen und beschreiben, wie man das bewerkstelligen kann.

    Es gibt unheimlich viele Wege, auf eine USB-Schnittstelle zuzugreifen. Ich habe den Weg über Java gewählt, weil mit der frei verfügbaren Bibliothek usb4java (LGPL-Lizenz) der Zugriff sehr schön programmierbar ist und ich mittlerweile mehr Erfahrung mit "gemanagten" Sprachen als mit purem C/C++ habe. Aber das ist Geschmackssache...

    Wie bereits angeführt, habe ich die Library usb4java benutzt. Dieses Package kann man unter http://usb4java.org/ downloaden. Dort finden sich auch sehr gute Anleitungen, an denen ich mich orientiert habe.

    usb4java erlaubt zwei verschiedene Zugriffsverfahren, einmal die harte Tour (die "low-level" libusb API) und einmal die warmherzig zuvorkommende Variante (die high-level "javax-usb" API). Letztere ist objektorientiert, ereignisgesteuert und feuert Exceptions im Fehlerfall, so dass die Abfrage negativer Rückgabewerte oft entfallen kann. Ich mags dekadent und nutze die high-level-API.

    Meine wichtigste Einstiegsmethode heißt "sendBytesToDevice" und soll eine beliebe Menge an Bytes an ein USB-Device senden. Zusätzlich muss die Methode wissen, welches USB-Device ich denn nun ansprechen möchte. Dafür habe ich zwei Möglichkeiten vorgesehen:
    1. Ich gebe die VendorID und die ProduktID des Devices an. Die Angaben liefert das Shellkommando "lsusb" als zwei per Doppelpunt getrennte Hex-Zahlen.
    2. Ich weiß, dass nur genau ein Device mit genau meinem gewünschten Typ (in diesem Fall Printer) angeschlossen ist. In diesem Fall gebe ich use_first_found_printer = true an, so dass productId und vendorId ignoriert werden.

    Das Programm soll an allen USBDevices nach dem gesuchten Gerät suchen (man könnte die Suche auch auf USBPorts/Interfaces einschränken - vielleicht interessant, wenn man zwei Drucker gleichen Modells unterscheiden möchte).

    Sicherlich kann man den Quelltext noch anhübschen und wahrscheinlich auch eleganter und fehlertoleranter aufbauen, aber ich möchte in erster Linie zeigen, wie das Verfahren funktioniert. Ich habe versucht, den Quelltext so zu kommentieren, dass er leicht verständlich ist. Bei Fragen oder Fehlern einfach melden... :)


     
    So, und jetzt noch ein Wort zu den Zugriffsrechten: Normalerweise darf nur Root auf die UsbDevices direkt zugreifen. Es macht aber durchaus Sinn, das Programm auch als "normaler" Benutzer ausführen zu können und diesem Benutzer oder einer Gruppe den Zugriff auf ein bestimmtes Usb-Gerät zu erlauben.

    Dazu kann man im Verzeichnis /etc/udev/rules.d eine Datei anlegen, deren Namen mit einer Zahl beginnt (Priorität) und mit ".rules" endet, z.B. 50-usb-zugriff.rules. In diese gehört die Information, wer auf welches Usb_Device schreiben darf. Der Inhalt sieht beispielsweise so aus:

    Code
    SUBSYSTEM=="usb", ATTR{idVendor}=="4348", ATTR{idProduct}=="5584", MODE="0666",GROUP="users"

    Damit haben die Benutzer der Gruppe "users" Lese- und Schreibrechte auf das Usb-Device mit der VendorId 4348 und der ProduktId 5584.

    Ich hoffe, dieses Tutorial ist für den einen oder anderen hilfreich... :)


    Stefan

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!