Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.
Raspberry als Sane-Scannerserver

Epson-Scanner mit dem Raspberry Pi betreiben – mit saned, QEMU und Debian/amd64-Chroot

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.

Inhalt
  1. Voraussetzungen
  2. Vorbereitung
  3. Debian/amd64-Chroot erstellen
  4. Bind-Mounts
  5. Epson-Treiber im Chroot
  6. Konfiguration im Chroot
  7. saned im Chroot starten
  8. Host konfigurieren
  9. Test
  10. Automatischer Start (systemd)
  11. Tipp bei Port-Konflikten
  12. Udev-Regel gegen Autosuspend
  13. Anwendung & Benchmark
  14. Fazit

 

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

 

Benchmark – Raspberry Pi 3B (300 dpi · Color · 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
Benchmark – Raspberry Pi 4 (300 dpi · Color · PNG)
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.

Wir benutzen Cookies

Wir nutzen Cookies auf unserer Website. Einige von ihnen sind essenziell für den Betrieb der Seite, während andere uns helfen, diese Website und die Nutzererfahrung zu verbessern (Tracking Cookies). Sie können selbst entscheiden, ob Sie die Cookies zulassen möchten. Bitte beachten Sie, dass bei einer Ablehnung womöglich nicht mehr alle Funktionalitäten der Seite zur Verfügung stehen.