🐞Die SANE-API im Debugger
Ein kompletter Scan ist eine feste Folge von C-Aufrufen. Stelle Modus, Auflösung und Bereich ein, wähle ein Szenario – und gehe den Ablauf Aufruf für Aufruf durch. Rechts baut sich das Bild so auf, wie die Bytes aus sane_read() kommen.
🧪
Simulation im Browser. Diese Seite steuert keinen echten Scanner an – der Server hat keinen, und ein öffentlich erreichbarer Scanner wäre ein Sicherheitsrisiko. Der simulierte Scanner bildet das Verhalten der SANE-API nach (Vorbild: das SANE-Test-Backend
test), alle Zahlen werden mit den echten Formeln berechnet.Schritt 1 / 27 · Tasten ← →
init
sane_init()
SANE_STATUS_GOODSANE_Int version_code; status = sane_init(&version_code, auth_callback);
Ergebnis
version_code = 0x0100001C = SANE_VERSION_CODE(1, 0, 28)
→ Major 1: Frontend und Backend sind kompatibel
Erster Aufruf überhaupt. Das Backend initialisiert sich und liefert seinen Versionscode. Nur die Major-Version entscheidet über Kompatibilität. Der optionale auth_callback wird aufgerufen, wenn ein Gerät Benutzer/Passwort verlangt (z. B. saned mit saned.users). Build 28 ist der Wert des echten test-Backends.
sane_init
Geräteliste
kein Handle
Leerlauf
🗺️Code-Flow laut Standard
sane_init()
│
├─ sane_get_devices() (jederzeit, kann langsam sein)
│
├─ sane_open("backend:gerät")
│ │
│ ├─ sane_get_option_descriptor() ┐ beliebig gemischt,
│ ├─ sane_control_option() ├ nach RELOAD_OPTIONS
│ ├─ sane_get_parameters() (Schätzung) ┘ neu einlesen
│ │
│ ├─ sane_start() ◄──────────────┐ nächster Rahmen
│ │ ├─ sane_get_parameters() │ bzw. nächste Seite
│ │ └─ sane_read() … EOF ──────┘
│ │
│ ├─ sane_cancel() (immer, auch nach EOF)
│ └─ sane_close()
│
sane_exit()| Funktion | Zweck |
|---|---|
| sane_init(&version, auth) | Backend initialisieren, Versionscode zurück |
| sane_exit() | alles freigeben – immer als Letztes |
| sane_get_devices(&list, local_only) | Liste der Geräte (NULL-terminiert) |
| sane_open(name, &h) / sane_close(h) | Gerät öffnen/schließen |
| sane_get_option_descriptor(h, n) | Beschreibung von Option n |
| sane_control_option(h, n, action, &v, &info) | Option lesen / setzen / automatisch |
| sane_get_parameters(h, &p) | Format, Pixel/Zeile, Bytes/Zeile, Zeilen, Tiefe |
| sane_start(h) | Aufnahme eines Rahmens starten |
| sane_read(h, buf, maxlen, &len) | nächsten Datenblock lesen |
| sane_cancel(h) | Vorgang beenden – auch nach EOF Pflicht |
| sane_set_io_mode(h, non_blocking) | blockierend (Standard) oder nicht blockierend |
| sane_get_select_fd(h, &fd) | Dateideskriptor für select()/poll() |
| sane_strstatus(status) | Statuscode als Text |
🚦Status-Codes (SANE_Status)
| Code | Name | sane_strstatus() | Bedeutung |
|---|---|---|---|
| 0 | SANE_STATUS_GOOD | "Success" | Aufruf erfolgreich. |
| 1 | SANE_STATUS_UNSUPPORTED | "Operation not supported" | Das Backend unterstützt die Operation nicht (z. B. nicht blockierendes Lesen). |
| 2 | SANE_STATUS_CANCELLED | "Operation was cancelled" | Vorgang wurde mit sane_cancel() abgebrochen. |
| 3 | SANE_STATUS_DEVICE_BUSY | "Device busy" | Gerät ist belegt (z. B. von einem anderen Programm geöffnet) – später erneut versuchen. |
| 4 | SANE_STATUS_INVAL | "Invalid argument" | Ungültiges Argument – z. B. unbekannter Gerätename bei sane_open() oder unzulässiger Optionswert. |
| 5 | SANE_STATUS_EOF | "End of file reached" | Kein Fehler: das Ende des aktuellen Rahmens ist erreicht. |
| 6 | SANE_STATUS_JAMMED | "Document feeder jammed" | Papierstau im automatischen Einzug (ADF). |
| 7 | SANE_STATUS_NO_DOCS | "Document feeder out of documents" | Der Einzug ist leer – bei --batch das normale Ende. |
| 8 | SANE_STATUS_COVER_OPEN | "Scanner cover is open" | Deckel bzw. Klappe des Scanners ist offen. |
| 9 | SANE_STATUS_IO_ERROR | "Error during device I/O" | Fehler bei der Kommunikation (USB, Netzwerk, SCSI). |
| 10 | SANE_STATUS_NO_MEM | "Out of memory" | Speicher reicht nicht. |
| 11 | SANE_STATUS_ACCESS_DENIED | "Access to resource has been denied" | Zugriff verweigert – z. B. saned-Benutzer/Passwort falsch. |
| 12 | SANE_STATUS_WARMING_UP | "Lamp not ready, please retry" | Lampe wärmt noch auf (Erweiterung, nicht im Standard 1.06). |
| 13 | SANE_STATUS_HW_LOCKED | "Scanner mechanism locked for transport" | Transportsicherung ist noch verriegelt (Erweiterung, nicht im Standard 1.06). |
🧑💻Minimales Frontend in C
So wenig braucht ein eigenes Scanprogramm – Fehlerbehandlung gekürzt. Übersetzen mit: cc scan.c -o scan $(pkg-config --cflags --libs sane-backends)
#include <sane/sane.h>
#include <stdio.h>
int main(void) {
SANE_Int version;
SANE_Handle h;
SANE_Parameters p;
SANE_Byte buf[32768];
SANE_Int len;
SANE_Status st;
sane_init(&version, NULL);
if (sane_open("test:0", &h) != SANE_STATUS_GOOD) { sane_exit(); return 1; }
sane_start(h);
sane_get_parameters(h, &p);
printf("%d x %d Pixel, %d Bytes/Zeile\n", p.pixels_per_line, p.lines, p.bytes_per_line);
FILE *out = fopen("scan.raw", "wb");
while ((st = sane_read(h, buf, sizeof buf, &len)) == SANE_STATUS_GOOD)
fwrite(buf, 1, len, out);
fclose(out);
if (st != SANE_STATUS_EOF) fprintf(stderr, "Fehler: %s\n", sane_strstatus(st));
sane_cancel(h);
sane_close(h);
sane_exit();
return 0;
}