16.12.2007

Kartenleser in Linux

default

 

USB-Kartenleser und USB-Memorystick (USB-Disk) unter Linux

Ich hatte mir einen USB-Kartenleser ("7 in 1") gekauft und eingebaut. Und dann "lief" er nicht. Jetzt läuft er, aber es war eine größere Operation. Ich schreibe es mal auf, für die Anderen zum Abgucken:

Im Kernel muß drin sein: EHCI Support, UHCI Support (bzw. OHCI Support, je nach Mainboard), USB Mass Storage Support und ein Treiber für den Chip auf dem jeweiligen Kartenleser. Das ist die erste Schwierigkeit: Welcher? Ich habe erstmal einfach alle verfügbaren Chips angewählt. Wenn der Leser eingebaut ist, sieht man in /proc/bus/usb das, was das Kernel bis jetzt sieht:

 

/proc/bus/usb:

/001
/002
devices

 

/proc/bus/usb/devices:

T:   Bus=02 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=   1 Spd=12   MxCh= 2
B:   Alloc=   0/900 us ( 0%), #Int=   0, #Iso=   0
D:   Ver= 1.10 Cls=09(hub   ) Sub=00 Prot=00 MxPS=64 #Cfgs=   1
P:   Vendor=0000 ProdID=0000 Rev= 2.06
S:   Manufacturer=Linux 2.6.16 uhci_hcd
S:   Product=UHCI Host Controller
S:   SerialNumber=0000:00:07.3
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=   0mA
I:   If#= 0 Alt= 0 #EPs= 1 Cls=09(hub   ) Sub=00 Prot=00 Driver=hub
E:   Ad=81(I) Atr=03(Int.) MxPS=     2 Ivl=255ms

T:   Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=   2 Spd=12   MxCh= 0
D:   Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=   1
P:   Vendor=0ea0 ProdID=2126 Rev= 2.00
S:   Manufacturer=OTi
S:   Product=USB Multi- Card Reader
S:   SerialNumber=0123456789abcdef
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=500mA
I:   If#= 0 Alt= 0 #EPs= 3 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:   Ad=81(I) Atr=02(Bulk) MxPS=   64 Ivl=0ms
E:   Ad=02(O) Atr=02(Bulk) MxPS=   64 Ivl=0ms
E:   Ad=83(I) Atr=03(Int.) MxPS=     2 Ivl=1ms

T:   Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=   1 Spd=12   MxCh= 2
B:   Alloc=   0/900 us ( 0%), #Int=   0, #Iso=   0
D:   Ver= 1.10 Cls=09(hub   ) Sub=00 Prot=00 MxPS=64 #Cfgs=   1
P:   Vendor=0000 ProdID=0000 Rev= 2.06
S:   Manufacturer=Linux 2.6.16 uhci_hcd
S:   Product=UHCI Host Controller
S:   SerialNumber=0000:00:07.2
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=   0mA
I:   If#= 0 Alt= 0 #EPs= 1 Cls=09(hub   ) Sub=00 Prot=00 Driver=hub
E:   Ad=81(I) Atr=03(Int.) MxPS=     2 Ivl=255ms

Oben und unten sind die beiden USB-Hostcontroller, in der Mitte ist ein Kartenleser von OTI. Da steht: "Driver=usb-storage", das ist das Kernelmodul 'usb_storage', ob es geladen ist, sieht man mit 'lsmod'.

Weil der Leser jetzt noch nicht "läuft", sollte man (eigentlich vor dem Kauf) klären, ob er denn überhaupt unterstützt wird.

Auf der Hardwareseite linuxhardware.html habe ich u.a. ein Link zu Listen mit USB-Geräten. Die Seiten sind schon älter, aber die Chips in den USB-Kartenlesern ändern sich offenbar nicht so schnell, deshalb wird man immer noch fündig. "Vendor=0ea0 ProdID=2126", damit geht man z.B. auf http://www.qbik.ch/usb/devices/ und sucht nach "0ea0". Dann landet man auf einer Seite, wo man sehr schnell findet: "0ea0:2126", das ist der Leser, und er ist grün angehakt. Unter "show" wird angezeigt: "Driver usb-storage", also weiß man immer noch nicht, welcher der angewählten Chiptreiber der richtige war. Aber man kann nicht alles haben.

'usb-storage' läßt eine Speicherkarte oder eine USB-Disk "von drinnen her" aussehen wie ein SCSI-Laufwerk, deshalb braucht man auch noch 'sd_mod' ("SCSI Disk Support").

 

/proc/scsi:

/usb-storage (das wird von 'usb-storage' hergebiemt)
device_info (das ist nur eine lange Liste)
scsi (das sind die sichtbaren SCSI-Geräte)

 

/proc/scsi/usb-storage:

0

 

/proc/scsi/usb-storage/0:

Host scsi0: usb-storage
Vendor: OTi
Product: USB Multi- Card Reader
Serial Number: 0123456789abcdef
Protocol: Transparent SCSI
Transport: Bulk
Quirks:

Das ist der Kartenleser.

 

/proc/scsi/scsi:

Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: OTi           Model: CF CARD Reader     Rev: 2.00
  Type:     Direct-Access                                       ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 00 Lun: 01
  Vendor: OTi           Model: SM CARD Reader     Rev: 2.00
  Type:     Direct-Access                                       ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 00 Lun: 02
  Vendor: OTi           Model: SD CARD Reader     Rev: 2.00
  Type:     Direct-Access                                       ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 00 Lun: 03
  Vendor: OTi           Model: MS CARD Reader     Rev: 2.00
  Type:     Direct-Access                                       ANSI SCSI revision: 02

Das sind die vier Kartenslots in dem Kartenleser.

Wenn beide geladen sind, und es ist eine Speicherkarte (SM-Card) eingelegt, erscheinen (bei mir):

 

/proc/partitions:

    [hda 1-...]
    8       16             4000 sdb (das ist die eingelegte SM-Karte)

 

/dev:

    sdb

In den Udev-Regeln habe ich:

 

/etc/udev/rules.d/my-rules:

[anderer Kram]
KERNEL="sd[a-z]",                                   GROUP="floppy"
KERNEL="sd[a-z][0-9]*",                       GROUP="floppy"

"Group Floppy" mache ich, damit ich es als einfacher User mounten kann.

In der File-System-Table habe ich:

 

/etc/fstab:

[anderer Kram]
/dev/sdb /sdb auto defaults,user,noauto,dmask=7,fmask=117,gid=7 0 0
/dev/sdb1 /sdb1 auto defaults,user,noauto,dmask=7,fmask=117,gid=7 0 0

Änderung 13.12.2007: Da0 die Option "sync" fehlt, erscheint auf den ersten Blick seltsam. Es ist ja bei einem herausnehmbaren Speichermedium eigentlich sinnvoll, mit "sync" zu mounten, damit jede Schreiboperation sofort erfolgt und nicht wartet, bis das Kernel mal zufällig Zeit hat. Aber der Linuxtreiber für das Dateisystem "vfat", das normalerweise auf den USB-Sticks liegt, hat einen versteckten Bug, der dazu führt, daß nicht nach jeder Datei die FAT (die Liste der belegten Blöcke) neu geschrieben wird, sondern nach jedem einzelnen Block. Und das führt dazu, daß das Flash-Memory auf dem Stick nach kurzer Zeit verbraucht ist. Außerdem macht es Schreibvorgänge sehr langsam.

 

Und als Mountpoints habe ich:

/sdb
/sdb1

Dann sage ich: 'mount /sdb' und kriege zwar eine Fehlermeldung, aber es erscheint auch noch:

 

/dev:

    sdb
    sdb1

Und /dev/sdb1 ist die Partition, die ich dann tatsächlich mounten kann.

Der Grund, warum nicht gleich sdb1 erscheint, kann sein, daß 'udev' noch nicht so ganz fertig ist. Jedes Kernel braucht im Augenblick eine andere Mindestversion von 'udev' und 'hotplug', und mein System ist schon wieder ein Dreivierteljahr alt. Es kann aber auch einfach daran liegen, daß ich mit 'udev' nicht gut genug umgehen kann und die Rules anders aussehen müßten.

Damit ich nicht immer von Hand mounten muß, habe ich mir ein kleines Skript in /usr/local/bin geschrieben. Das mountet sdb, speichert die Fehlermeldung, mountet sdb1, zeigt ggfs. ein Meldungsfenster mit der Fehlermeldung, startet meinen Filemanager mit /sdb1. Wenn ich den wieder schließe, unmountet es sdb1 wieder, und ich kann die Karte herausziehen, ohne daß das Kernel anfängt zu weinen:

 

/usr/local/bin/premount:

#!/bin/sh
rm -f /tmp/premount.err
mount /sdb 2>>/tmp/premount.err
test "$?" != "0" &&
sleep 2 &&
mount /sdb1 2>>/tmp/premount.err
test "$?" = "0" &&
"$1" /sdb1 2>>/tmp/premount.err
RES=$?
umount /sdb1
umount /sdb
echo "Errorcode $RES" >>/tmp/premount.err
[ "$RES" != "0" ] &&
[ "$RES" != "123" ] &&
xmessage -center -file /tmp/premount.err

Das Skript habe ich auf einen Button im Startpanel gelegt und es wird aufgerufen mit: '/usr/local/bin/premount xffm', weil xffm mein Filemanager ist. Hier sieht man die Buttons für die Speicherkarten-Laufwerke: nw4.html (unten links).

Das hier ist nicht das Originalskript, das war zu lang, ich habe es gekürzt. Das Originalskript bedient natürlich auch die anderen Slots und auch einen USB-Memorystick, und es wird aufgerufen mit: '/usr/local/bin/premount xffm /sdb1'.

Dann habe ich hier Buttons für sda1 bis sde1. Das Skript liegt im Tarball meiner Install- und Deinstallskripten auf http://www.abatz.de/inst.html unter "Download der Skripten", bitte in ein leeres (!) Directory kopieren, dann entpacken, dann liegt 'premount' in usr-local-bin/ und die Icons für die verschiedenen Karten in usr-local-share-icons/ (Die SM-Karte heißt z.B. sm2.ppm)

abatz.de Jörn Abatz - Technische Software Impressum