Viele ältere Epson-Scanner wie der Epson Perfection V300 Photo funktionieren unter Linux nur mit proprietären Treibern, die nicht immer für ARM-Architekturen (z. B. Raspberry Pi) verfügbar sind. Da Epson aber x86_64-Treiber bereitstellt, lässt sich der Scanner auf einem Raspberry Pi nur über einen emulierten Debian/amd64-Chroot mit QEMU betreiben.
Diese Anleitung beschreibt, wie du auf einem Raspberry Pi 3B (oder ähnlichem Modell) einen Scannerserver mit saned einrichtest, der trotz fehlender ARM64-Treiber funktioniert.
1. Voraussetzungen
- Raspberry Pi mit Raspberry Pi OS / Debian ARM64 (Bookworm)
- USB-Scanner: Epson GT-F720 / Perfection V30/V300
- Internetverbindung & sudo-Zugriff
2. Vorbereitung
sudo apt-get update && sudo apt-get install -y debootstrap qemu-user-static binfmt-support sane-utils usbutils
3. Debian/amd64-Chroot erstellen
sudo debootstrap --arch=amd64 bookworm /srv/debian-amd64 http://deb.debian.org/debian
sudo cp /usr/bin/qemu-x86_64-static /srv/debian-amd64/usr/bin/
4. Bind-Mounts
Damit der Scanner im Chroot sichtbar ist:
sudo mount --rbind /dev /srv/debian-amd64/dev
sudo mount --rbind /proc /srv/debian-amd64/proc
sudo mount --rbind /sys /srv/debian-amd64/sys
Optional: sudo mount --rbind /run /srv/debian-amd64/run
5. Epson-Treiber im Chroot
sudo chroot /srv/debian-amd64 /bin/bash
dpkg -i iscan_2.30.4-2_amd64.deb iscan-data_1.39.2-1_all.deb esci-interpreter-gt-f720_1.0.0-1_amd64.deb
apt-get -f install
Hinweis: Treiberpakete findest du auf Epsons Linux-Seite. Falls Abhängigkeiten fehlen, hilft apt-get install -f.
6. Konfiguration im Chroot
nano /etc/sane.d/dll.conf
epkowa
nano /etc/sane.d/epkowa.conf
interpreter /usr/lib/esci/libesci-interpreter-gt-f720.so
nano /etc/sane.d/saned.conf
127.0.0.1
localhost
7. saned im Chroot starten
saned -l -e -d128 -u saned -b 127.0.0.1 -p 6566
8. Host konfigurieren
sudo nano /etc/services
# Local services
sane-port 6566/tcp sane saned
sudo nano /etc/sane.d/dll.conf
net
sudo nano /etc/sane.d/net.conf
localhost
9. Test
scanimage -L
scanimage -d "net:127.0.0.1:epkowa:interpreter:001:008" --format=png --resolution 300 > ~/test.png
10. Automatischer Start mit systemd
10.1. Bash Skript
sudo nano /usr/local/sbin/start-saned-chroot.sh
#!/usr/bin/env bash
set -euo pipefail
CHROOT="/srv/debian-amd64"
PORT="6566"
INTERPRETER="/usr/lib/esci/libesci-interpreter-gt-f720.so"
# Bind mounts
for d in dev proc sys; do
mkdir -p "$CHROOT/$d"
mountpoint -q "$CHROOT/$d" || mount --rbind "/$d" "$CHROOT/$d"
done
# saned user
if ! chroot "$CHROOT" getent passwd saned >/dev/null; then
chroot "$CHROOT" adduser --system --group --no-create-home saned
fi
# Start saned
exec chroot "$CHROOT" /usr/sbin/saned -l -e -d128 -u saned -b 0.0.0.0 -p "$PORT"
10.2. systemd Servicedatei
sudo nano /etc/systemd/system/saned-chroot.service
[Unit]
Description=SANEd inside amd64 chroot on port 6566
After=network-online.target local-fs.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/sbin/start-saned-chroot.sh
ExecStopPost=/bin/umount -R /srv/debian-amd64/dev
ExecStopPost=/bin/umount -R /srv/debian-amd64/proc
ExecStopPost=/bin/umount -R /srv/debian-amd64/sys
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=multi-user.target
10.3. Neustarten und als Systemdienst aktivieren
sudo systemctl daemon-reload
sudo systemctl enable --now saned-chroot.service
journalctl -u saned-chroot -f
11. Tipp bei Port-Konflikten
Falls auf dem Host irgendein Service, z.B. saned.socket, den Port 6566 blockiert, dann wie folgt prüfen und deaktivieren:
ss -ltnp | grep ':6566'
sudo systemctl disable --now saned.socket
12. Udev-Regel gegen USB-Autosuspend (optional)
Udev überwacht Hotplug-Ereignisse und erstellt beim Anschluss eines neuen Geräts im Verzeichnis /dev eine zugehörige Gerätedatei mit Regeln und Rechten. Diese sogenannten Rules legen fest, was geschieht, sobald Udev das Gerät erkennt. USB-Autosuspend spart Energie, indem inaktive USB-Geräte automatisch in den Energiesparmodus versetzt werden. Bei empfindlichen Geräten wie Scannern, Audio-Interfaces oder WLAN-Sticks kann das jedoch Verbindungsabbrüche verursachen – hier sollte Autosuspend via Udev-Regel gezielt deaktiviert werden.
lsusb # Beispiel: 04b8:0131
sudo nano /etc/udev/rules.d/99-usb-autosuspend.rules
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b8", ATTR{idProduct}=="0131", TEST=="power/control", ATTR{power/control}="off"
sudo udevadm control --reload-rules
sudo reboot
13. Anwendung & Benchmark
Das folgende Skript misst die Scan-Geschwindigkeit und den Durchsatz:
Das Skript:
• erkennt automatisch dein net:…:epkowa:interpreter:… Gerät (oder du gibst -d explizit an),
• macht einen Warm-up-Scan (nicht getimed),
• führt N Messläufe durch,
• zeigt für jeden Lauf Zeit, Größe, Durchsatz (MB/s),
• und fasst die Durchschnittswerte zusammen.
13.1. Skript erstellen
nano ~/scan_benchmark.sh
#!/usr/bin/env bash
# scan_benchmark.sh — simple scanner throughput benchmark via SANE
# Works with net backend (e.g., saned in amd64 chroot @ localhost:6566)
set -euo pipefail
export LC_ALL=C
OUTDIR="${OUTDIR:-$HOME/scan-bench}"
RUNS="${RUNS:-3}"
RES="${RES:-300}"
MODE="${MODE:-Color}" # Color | Gray | Lineart
FORMAT="${FORMAT:-pnm}" # pnm | png | tiff
DEVICE="${DEVICE:-}" # override with -d or env
LIST_ONLY="${LIST_ONLY:-0}" # set to 1 to just list detected devices and exit
usage() {
cat <<'EOF'
Usage: scan_benchmark.sh [options]
Options:
-o DIR Output directory (default: $HOME/scan-bench)
-n RUNS Number of timed runs (default: 3)
-r DPI Resolution in DPI (default: 300)
-m MODE Mode: Color | Gray | Lineart (default: Color)
-f FORMAT Output format: pnm | png | tiff (default: pnm)
-d DEVICE Explicit SANE device string (default: auto-detect)
-l List detected devices and exit
-h Show this help
Examples:
scan_benchmark.sh -n 3 -r 300 -m Color -f pnm
DEVICE="net:127.0.0.1:epkowa:interpreter:001:008" scan_benchmark.sh
EOF
}
while getopts ":o:n:r:m:f:d:lh" opt; do
case "$opt" in
o) OUTDIR="$OPTARG" ;;
n) RUNS="$OPTARG" ;;
r) RES="$OPTARG" ;;
m) MODE="$OPTARG" ;;
f) FORMAT="$OPTARG" ;;
d) DEVICE="$OPTARG" ;;
l) LIST_ONLY=1 ;;
h) usage; exit 0 ;;
\?) echo "Unknown option -$OPTARG"; usage; exit 1 ;;
:) echo "Option -$OPTARG requires an argument."; usage; exit 1 ;;
esac
done
mkdir -p "$OUTDIR"
# --- Helpers (numeric-safe, locale-neutral via LC_ALL=C) ---
bytes_to_mb() { awk -v b="$1" 'BEGIN{printf "%.2f", b/1048576}'; }
ns_to_sec() { awk -v ns="$1" 'BEGIN{printf "%.3f", ns/1e9}'; }
throughput_mbps(){ awk -v b="$1" -v ns="$2" 'BEGIN{ if(ns>0) printf "%.2f", (b/1048576)/(ns/1e9); else print 0 }'; }
echo "== System =="
echo "Date: $(date -Is)"
echo "Host: $(hostname)"
uname -a || true
command -v lscpu >/dev/null 2>&1 && lscpu | sed 's/^/CPU: /' || true
echo
command -v scanimage >/dev/null 2>&1 || { echo "scanimage not found. Install sane-utils."; exit 1; }
discover_devices() {
scanimage -f "%d\n" 2>/dev/null | sed '/^$/d' || true
if [ "${PIPESTATUS[0]}" -ne 0 ]; then
scanimage -L 2>/dev/null | sed -n 's/^device [`"'"'"]\([^`"'"'"']*\)[`"'"'"].*$/\1/p'
fi
}
if [[ "$LIST_ONLY" -eq 1 ]]; then
echo "Detected devices:"
discover_devices | nl -ba
exit 0
fi
if [[ -z "$DEVICE" ]]; then
echo "Auto-detecting device..."
mapfile -t devs < <(discover_devices)
if [[ "${#devs[@]}" -eq 0 ]]; then
echo "No SANE devices found. Check your net.conf / saned."
exit 2
fi
for d in "${devs[@]}"; do [[ "$d" =~ ^net:.*interpreter: ]] && DEVICE="$d" && break; done
if [[ -z "$DEVICE" ]]; then
for d in "${devs[@]}"; do [[ "$d" =~ ^net: ]] && DEVICE="$d" && break; done
fi
[[ -z "$DEVICE" ]] && DEVICE="${devs[0]}"
DEVICE="$(printf "%s" "$DEVICE" | tr -d '\r' | sed 's/\\n$//; s/[[:space:]]*$//')"
echo "Using device: $DEVICE"
else
DEVICE="$(printf "%s" "$DEVICE" | tr -d '\r' | sed 's/\\n$//; s/[[:space:]]*$//')"
echo "Using device (from -d/DEVICE): $DEVICE"
fi
echo
echo "Warm-up scan (not timed)..."
WARM="$OUTDIR/warmup.$FORMAT"
if ! scanimage -d "$DEVICE" --mode "$MODE" --resolution "$RES" --format="$FORMAT" > "$WARM"; then
echo "Warm-up scan failed; device may not support chosen mode/resolution/format."
echo "Tip: try -m Gray and/or -f pnm"
exit 3
fi
echo "Warm-up output: $WARM ($(stat -c %s "$WARM" 2>/dev/null || echo 0) bytes)"
echo
total_ns=0
total_bytes=0
echo "== Timed runs =="
for i in $(seq 1 "$RUNS"); do
ts=$(date +%s%N)
out="$OUTDIR/scan_${i}_$(date +%Y%m%d_%H%M%S).$FORMAT"
if ! scanimage -d "$DEVICE" --mode "$MODE" --resolution "$RES" --format="$FORMAT" > "$out"; then
echo "Run $i failed."; exit 4
fi
te=$(date +%s%N)
dur_ns=$(( te - ts ))
size_b=$(stat -c %s "$out")
secs=$(ns_to_sec "$dur_ns")
mb=$(bytes_to_mb "$size_b")
mbps=$(throughput_mbps "$size_b" "$dur_ns")
echo "Run $i: ${secs}s, size=${mb} MB, throughput=${mbps} MB/s → $out"
total_ns=$(( total_ns + dur_ns ))
total_bytes=$(( total_bytes + size_b ))
done
avg_ns=$(( total_ns / RUNS ))
avg_secs=$(ns_to_sec "$avg_ns")
avg_mb=$(bytes_to_mb "$total_bytes")
avg_mbps=$(throughput_mbps "$total_bytes" "$avg_ns")
echo
echo "== Summary =="
echo "Runs: $RUNS | Resolution: ${RES}dpi | Mode: $MODE | Format: $FORMAT"
echo "Avg time: ${avg_secs}s | Avg throughput: ${avg_mbps} MB/s"
echo "Output dir: $OUTDIR"
13.2. Skript ausführbar machen
chmod +x ~/scan_benchmark.sh
13.3. Benchmarkwerte
~/scan_benchmark.sh -n 3 -r 300 -m Color -f png
| Lauf | Zeit | Größe | Durchsatz |
|---|---|---|---|
| 1 | 51.734 s | 13.46 MB | 0.26 MB/s |
| 2 | 52.224 s | 13.46 MB | 0.26 MB/s |
| 3 | 53.124 s | 13.47 MB | 0.25 MB/s |
| Ø | 52.361 s | 0.77 MB/s |
| Lauf | Zeit | Größe | Durchsatz |
|---|---|---|---|
| 1 | 40.133 s | 13.45 MB | 0.34 MB/s |
| 2 | 40.789 s | 13.45 MB | 0.33 MB/s |
| 3 | 40.803 s | 13.45 MB | 0.33 MB/s |
| Ø | 40.575 s | 0.99 MB/s |
14. Fazit
Trotz fehlender ARM64-Treiber lässt sich der Epson GT-F720 / Perfection V30/V300 mit saned im QEMU-Chroot zuverlässig auf einem Raspberry Pi betreiben. Der Scanner steht dann netzwerkweit über SANE zur Verfügung — ideal für ressourcenschonende Heimserver oder NAS-Geräte. Allerdings leidet die Performance unter dem QEMU-Chroot-Lösung. Falls man einen nativen Treiber für seinen Scanner besitzt, dann ist die Lösung optimal, insbesondere in Kombination mit Airscan. Dann ist sogar das direkte Scannen vom Mobiltelefon möglich.