Der Markt für Pheripheriegeräte mit USB-Anschluss wir immer größer. Die Inbetriebnahme dieser Geräte ist unter Linux jedoch nicht immer ganz einfach. Mit Kenntnissen über Linux-USB ist aber alles halb so wild, wie der folgende Artikel zeigt.
Eigentlich ist die Markteinführung des “Universial Serial Bus” (kurz USB) schon etwas länger her. 1996 entschlossen sich Intel, Compaq, Microsoft und NEC dazu, einen einfachen Standard zum Anschluss von Peripheriegeräten zu etablieren. Dabei sollte USB besonders benutzerfreundlich sein – so gibt es etwa nur noch zwei Steckertypen, die für alle Geräte verwendet werden: Uplink und Downlink, so dass man auch als Laie automatisch den richtigen Port verwendet. Ein weiterer Vorteil ist das Bussystem: an seriellen und parallelen Anschlüssen ist immer nur ein Gerät verwendbar – mit USB ist der gleichzeitige Betrieb von 127 Geräten möglich, sofern genügend HUBs zur Verfügung stehen. Die Geschwindigkeit von maximal 12 Mbit/Sekunde müssen sich dabei zwar alle Geräte teilen. Da aber ein einzelner menschlicher Benutzer kaum mehr als drei Geräte hoher Bandbreite gleichzeitig nutzen kann, ist dies nicht weiter tragisch. Auch lässt sich Bandbreite reservieren, zum Beispiel für einen empfindlichen USB-CD-Brenner. Dank der USB-Architektur benötigt man vom Rechner nur noch ein Kabel zum Schreibtisch. Über einen bequem erreichbaren HUB lassen sich dann Tastatur, Maus, Joystick und Grafiktablett anschließen. Bei Verwendung einer Tastatur oder eines Monitors mit integriertem Hub kann man nochmal Platz auf dem Schreibtisch sparen. Ein weiterer Vorteil von USB ist die Stromzufuhr: an jedem Port können bis zu 500mA abgegriffen werden – genug für Modems und für viele Scanner. Auch Lautsprecher ohne weiteren Strombedarf gibt es [1] – sie sind hauptsächlich für den Anschluss an Notebooks gedacht, denn gerade in diesem Einsatzgebiet hat man öfter keinen Stromanschluss in der Nähe.
Useless Serial Bus?
In den ersten paar Jahren seiner Existenz wurde der Universal Serial Bus von Kritikern gerne als “Useless Serial Bus” bezeichnet, da es weder Geräte noch Betriebssysteme gab, die damit etwas anfangen konnten. Heutzutage hat aber jeder PC mindestens zwei USB-Anschlüsse und die dazu passende Peripherie findet sich in den Computerläden wie Sand am Meer. Aber nur wenige Betriebssystem konnten sich auf Anhieb mit USB anfreunden – so blieben etwa Windows NT und Linux lange Zeit außen vor. Ob das Motto “Plug’n’Play” nun auch für Linux gilt, das soll diese Artikelreihe aufzeigen. Alle Distributoren, die etwas auf sich halten (z. B. SuSE, Caldera, Mandrake, Red Hat) , haben mittlerweile USB-Support. Mit echtem “Einstecken und Loslegen” kann man leider nicht immer rechnen – es wird oft nur der USB-Kern geladen. Deshalb schaden genauere Kenntnisse über Linux-USB nicht. Auch wenn der Kernel der verwendeten Distribution bereits mit USB umgehen kann, so kann es eventuell nötig sein, einen eigenen Betriebssystemkern zu backen, um alle angeschlossenen Peripheriegeräte zum Laufen zu bringen. Am Anfang steht deshalb oft die Erzeugung eines USB-fähigen Kernels. Zwar gibt es im normalen 2.2.x schon rudimentäre Ansätze, jedoch werden nur Mäuse und Tastaturen unterstützt – und auch diese nur nach manuellen Eingriffen in die Kernel-Konfigurationsdatei. Einfacher ist es bei der 2.4er Kernelserie. Hier ist eine ordentliche USB-Implementierung schon fester Bestandteil. Wer nicht so lange warten will bis der Kernel 2.4 seinen Teststatus offiziell ablegt, für den gibt es einen sogenannten “Backport-Patch”, in dem fast alle USB-Treiber aus 2.4 für den 2.2er Kernel umgeschrieben wurden [2]. Alle Distributionen mit USB-Support setzen diesen ein.
Erstellung eines USB-fähigen Kernels
- Als erstes besorgt man sich die frischen Kernel-Sourcen [3] und den Backport-Patch [2]. Es ist nicht empfehlenswert, den bei der Distribution mitgelieferten Kernel zu verwenden, da diese oft bereits mit diversen Patches versehen wurden, und es deshalb zu Konflikten mit dem USB-Backport kommen kann. Sollten noch weitere Features benötigt werden, welche nicht im Standardkernel enthalten sind (etwa ReiserFS), so müssen die Patches dafür ebenfalls aus dem Internet geladen und eingearbeitet werden.
- Auspacken und Patchen des Kernels
# tar -xvIf linux-2.2.17.tar.bz2 # cd linux # bzip2 -c -d ../usb-2.4.0-test2-pre2-for-2.2.16-v3.diff.bz2 | patch -p1 oder # gzip -c -d ../usb-2.4.0-test2-pre2-for-2.2.16-v3.diff.gz | patch -p1
Sollten Sie schon mal einen Kernel konfiguriert haben, oder bei der Distribution eine Konfigurationsdatei (.config) beiliegen, so kann man diese einfach in das neue entstandene Linux-Verzeichnis kopieren. Konfiguriert wird der Kernel auf der Konsole mit
# make menuconfig
oder unter X-Window mi
# make xconfig
im Verzeichnis /usr/src/linux (Voraussetzung: Kernel-Quellen und -Headerdateien sind hier installiert!) Hierbei ist darauf zu achten, dass alle zum Zugriff auf die Root-Partition notwendigen Treiber (ext2, ggf. SCSI) fest (und nicht modular) in den Kernel eingebunden werden. Bei der USB-Konfiguration selber ist es dagegen empfehlenswert, möglichst überall Module anzugeben, damit zwar bei Bedarf alle Treiber verfügbar sind, diese aber nicht unnötig ständig den Speicher belasten. Haben Sie alle Kernel-Sektionen durchgearbeitet, dann wird der Kernel mit
# make dep clean && make bzImage && make modules modules_install
kompiliert. Um den neuen Kernel booten zu können, muss man ihn nach /boot kopieren (cp arch/i386/bzImage /boot/2.2.16.usb und beim Bootloader eintragen. Wir betrachten hier exemplarisch Lilo. Am einfachsten kopiert man dabei einen schon vorhandenen Eintrag in der Datei /etc/lilo.conf, und ändert Kernel-Datei und label ab:
image=/boot/2.2.16.usb label=standard append="Bootparamter" read-only root=/dev/hdb5
Der Aufruf von lilo schreibt das Ganze schließlich in den Master Boot Record:
# lilo Added standard * Added usb
Der Stern markiert, welcher Eintrag aktiv ist. Das ist entweder der erste vorhandene, oder aber derjenige, der mit default= angegeben wurde. Für die weniger Mutigen unter Ihnen, die nicht an ihrer Bootkonfiguration drehen möchte, gibt es die weniger heikle Möglichkeit, den neuen Kernel von Diskette zu booten:
dd if=/boot/2.2.16.usb of=/dev/fd0
(alle Daten auf der Diskette werden beim anfertigen gelöscht).
USB zum Nachrüsten
Auch bei älteren Rechnern ist die Nachrüstung von USB möglich. Voraussetzung ist ein Steckplatz, der den Anforderungen von PCI V2.0 genügt, was auch bei 486-Motherboards gegeben sein sollte. So lief etwa eine USB-Hostcontroller PCI-Karte von Vivanco problemlos parallel zum integrierten USB-Controller auf dem Motherboard. Als Alternative zu einem extern herumstehenden Hub bietet sich also auch ein interner USB-PCI-Adapter an, wenn die Ports ausgehen.
Danach muss man noch in den Start-Scripts das Laden des USB-Kernels veranlassen. Dabei gibt es zwei verschiedene Typen an USB-Host-Controller: OHCI und UHCI. Während das “Open Host Controller Interface” meist in Compaq, iMacs, OPTi, SiS, ALi und vielen mehr zu finden ist, setzen Intel und VIA auf das Universal Host Controller Interface. Am sichersten findet man den Typ des Controllers heraus, indem man in /proc/pci nachsieht: UHCI arbeitet mit IO-Ports, OHCI-Register, wenn in den Speicherraum eingeblendet:
cat /proc/pci
Bus 0, device 7, function 2:
USB Controller: VIA Technologies VT 82C586 Apollo USB (rev 2).
Medium devsel. IRQ 9. Master Capable. Latency=64.I/O at 0xe400 [0xe401].
Bus 0, device 20, function 0:
USB Controller: CMD 670 (rev 6).
Medium devsel. IRQ 11. Master Capable. Latency=64. Min Gnt=2.Max Lat=4.
Non-prefetchable 32 bit memory at 0xe8001000 [0xe8001000].
Bei den ersten Experimenten mit USB ist es empfehlenswert, die Treiber von Hand zu laden, um sicherzugehen, dass die Controller erkannt werden:
modprobe usb-uhci # (oder usb-ohci) lsmod usb-uhci 21216 0 (unused) usbcore 46152 0 [usb-uhci]
Danach sollte man das “USB-Dateisystem” einbinden, denn damit erhält man detailierte Informationen über angeschlossene Geräte:
mount -t usbdevfs /proc/bus/usb /proc/bus/usb
Nun lässt sich mi
cat /proc/bus/usb/devices
nachsehen, welche Geräte angeschlossen sind, und ob es einen Treiber dafür gibt. Der Eintrag für ein Wacom Graphire USB Grafiktablett sähe etwa wie folgt aus:
T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=1.5 MxCh= 0 D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=056a ProdID=0010 Rev= 1.11 S: Manufacturer=WACOM S: Product=ET-0405-UV1.1-1 C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 40mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=wacom E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl= 10ms

/proc/bus/usb/devices«” width=”300″ height=”126″ />
Abbildung 2: Wichtige Einträge inDie wichtigsten Zeilen sind in Abbildung 2 erklärt. Das “P:”-Feld werden wir später noch brauchen, um ein Gerät eindeutig anzugeben, während das “I:”-Feld die Information enthält, ob ein passender Treiber geladen ist. Steht am Ende der Zeile (none), fühlt sich keiner der geladenen Treiber zuständig, und das Gerät kann nicht verwendet werden. Genaue Erläuterungen zu allen Feldern findet sich in /usr/src/linux/Documentation/usb/proc_usb_info.txt.
Die Geräte-Informationen lassen sich mit Hilfe von usbview grafisch ansprechend darstellen. Wenn es wie hier nur zwei Geräte sind, kann man noch direkt die Datei lesen, bei mehreren Hubs verliert man allerdings recht schnell den Überblick. Mit der Baumstruktur sieht man auch sehr schnell, welches Gerät an welchem Hub hängt. Zum Konzept, welches Gerät man wo anstöpselt, ist nur wenig zu sagen: USB-Tastaturen sollten generell direkt an den Rechner angesteckt werden, da man sonst Gefahr läuft, dass die Tastatur bei alten BIOS’en nicht sichtbar ist, und Sie somit auch beim Bootloader-Prompt nicht damit rechnen können. Desweiteren muss man darauf achten, dass pro Port an einem aktiven Gerät nur 500 mA Strom fließen dürfen. Es empfielt sich außerdem, an einen passiven Hub möglichst kein Modem oder Scanner anzuschließen – Ausnahmen bestätigen aber wie immer die Regel.
Module automatisch laden
Genau wie bei PCI können auch bei USB die Geräteinformationen einheitlich abgefragt werden, so dass jedes Betriebssystem eindeutig entscheiden kann, ob ein passender Treiber verfügbar ist (die Informationen tauchen dann in der vorher erwähnten /proc/bus/usb/devices auf). Unter Linux gibt es dafür mehrere Möglichkeiten. Beim Kernel 2.2.x muss dafür ständig ein Daemon laufen, der das usbfs abhört, bei Änderungen reagiert und gegebenenfalls die notwendigen Module nachlädt. Zur Auswahl stehen hier drei Projekte: usbd, jUSBD und usbmgr. Betrachten wir letzteren:
Während der Installation (dank RPM problemlos) entsteht das Verzeichnis /etc/usbmgr, in dem sich unter anderem die Datei usbmgr.conf befindet. Diese enthält pro Gerät einen Eintrag. Für ein Wacom USB-Grafiktablett und eine Logitech-Maus sehen die Einträge zum Beispiel wie folgt aus:
# ET-0405-UV1.1-1 [WACOM]|graphire|FAVO vendor 0x56a product 0x10 module evdev , mousedev , wacom #USB-PS/2 Mouse M-BA47 [Logitech] vendor 0x046d product 0xc002 module hid , usbmouse , mousedev
Aufgrund der Vielzahl an Herstellern von USB-Geräten sind noch nicht alle Geräte in der üblichen usbmgr.conf eingetragen. Dies lässt sich aber nachholen, indem man in der Datei /proc/bus/usb/devices die Hersteller- und Produkt-Nummer ermittelt und herausfindet, welche Module benötigt werden.
Beim kommenden Kernel 2.4 greift übrigens ein anderer Mechanismus: dort gibt es die Option, dass der Kernel das Laden der Module steuert. Dazu ruft er, sobald ein neues Gerät eingesteckt wird, die Datei /sbin/hotplug auf. Diese soll übrigen im Kernel 2.4 zur zentralen Anlaufstelle für im Betrieb wechselbaren Geräte werden, also neben USB-Geräten auch noch PCMCIA, SCSI und PCI-Karten (natürlich nur, wenn es die Hardware erlaubt).
Listing 1
USB-Startskript, Beispiel:
#!/bin/sh
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin
start_usb ()
{
modprobe -q usb-uhci >/dev/null 2>&1 ||\
modprobe -q usb-ohci >/dev/null 2>&1 ||\
modprobe -q uhci >/dev/null 2>&1 ||\
(echo "Kein USB-Kontroller gefunden";
rmmod usbcore>/dev/null 2>&1;return 1)
mount -t usbdevfs none /proc/bus/usb
usbmgr
return 0;
}
stop_usb ()
{
killall usbmgr >/dev/null 2>&1
umount /proc/bus/usb >/dev/null 2>&1
rmmod usb-ohci usb-uhci uhci >/dev/null 2>&1
return 0;
}
case "$1" in
start)
start_usb
;;
stop)
stop_usb
;;
*)
echo "Usage: $0 [start|stop]"
return 1
;;
esac
Leider arbeitet bisher noch keine einzige Distribution mit dynamischem Nachladen der Module (mit Ausnahme der noch experimentellen “Technologie Preview” von Caldera). Sowohl bei SuSE als auch bei Mandrake werden beim Starten alle vorher angegebenen Module statisch geladen. Bei diesen Distributionen kann aber bei Bedarf usbmgr nachinstalliert und der Aufruf von usbmgr im USB-Startskript (siehe Listing 1) ergänzt werden.
Wie bereits erwähnt, gibt es für die verschiedenen Geräte verschiedene Module. Bei USB gibt es außerdem mehrere standardisierte Geräteklassen (zum Beispiel: 0x02=Kommunikationsgerät, 0x09=Hub), die mit Linux keine Probleme bereiten sollten. Da jeder USB-Anschluss mit dem Root-Hub beginnt, ist der Treiber für Hubs schon im usbcore-Modul enthalten. Es sollte absolut jeder Hub problemlos funktionieren. Leider ist die USB-Spezifikation nicht umfassend, was zur Folge hat, dass viele Geräte unter Linux nicht funktionieren, weil die Hersteller proprietäre Protokolle verwenden. Welche Geräte unter Linux aber tatsächlich funktionieren und welche nicht, darauf gehen wir in den jeweiligen Einzelartikeln ein.






