From 49ad65435e114331e78f720a7985c23fbca91d45 Mon Sep 17 00:00:00 2001 From: Oliver Hofmann Date: Tue, 2 Jun 2026 10:30:43 +0200 Subject: [PATCH] Add design spec for kydriv Kyocera 3505ci Apple Silicon driver --- .../specs/2026-06-02-kydriv-design.md | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-02-kydriv-design.md diff --git a/docs/superpowers/specs/2026-06-02-kydriv-design.md b/docs/superpowers/specs/2026-06-02-kydriv-design.md new file mode 100644 index 0000000..6f177e4 --- /dev/null +++ b/docs/superpowers/specs/2026-06-02-kydriv-design.md @@ -0,0 +1,164 @@ +# kydriv — Kyocera 3505ci Treiber für Apple Silicon + +## Kontext + +Der Kyocera/TA 3505ci Multifunktionsdrucker erfordert zur Nutzung einen Abteilungscode (Kostenstelle). Der bisherige Intel-Mac-Treiber bot dafür ein Textfeld im Druckdialog. Der aktuelle Apple-Silicon-Treiber von Kyocera hat diese Funktion nicht. Dieses Projekt entwickelt einen Ersatztreiber für macOS auf Apple Silicon, der die fehlenden Funktionen — insbesondere die Kostenstelle — wiederherstellt. + +## Ursachenanalyse + +Der alte Intel-Treiber bestand aus drei Schichten: + +1. **APDialogExtension-Plugins** (`.plugin`-Bundles) — Objective-C/Cocoa-Panels im Druckdialog. Intel-only, von Apple deprecated. Zuständig für die UI (Textfelder, Checkboxen). +2. **CUPS-Filter** (`kyoprefilter_E`, `kyofilter_E`) — kompilierte Intel-Binaries. Zuständig für PostScript-Verarbeitung und Einschleusen von Gerätebefehlen. +3. **PPD-Datei** — Textdatei, architekturunabhängig. + +Auf Apple Silicon fehlen die Punkte 1 und 2. Der neue Kyocera-Treiber hat nur eine abgespeckte PPD ohne die Plugin-Mechanismen. + +## Lösungsansatz + +**PPD + Python CUPS-Filter**, verteilt als signiertes `.pkg`. + +- Die APDialogExtension-Plugins werden nicht ersetzt (deprecated API). Stattdessen werden Kostenstellen als benannte Optionen in der PPD geführt und per Preset gespeichert. +- Die Intel-Filter werden durch ein Python-Script ersetzt, das architekturunabhängig ist. +- Der Kyocera-Treiber wird vollständig umgangen — die Lösung ist eigenständig. + +## Komponenten + +``` +kydriv/ +├── ppd/ +│ └── TA3505ci_AS.ppd # modifizierte PPD +├── filter/ +│ └── kyofilter # Python CUPS-Filter +├── installer/ +│ ├── root/ # Dateisystem-Abbild für pkgbuild +│ │ ├── Library/Printers/PPDs/Contents/Resources/TA3505ci_AS.ppd +│ │ └── usr/libexec/cups/filter/kyofilter +│ ├── scripts/ +│ │ └── postinstall +│ └── build.sh +└── docs/superpowers/specs/ +``` + +**Datenfluss:** +``` +macOS App (PDF) → CUPS pdftops → PostScript → kyofilter (Python) → Drucker +``` + +## PPD-Datei (`TA3505ci_AS.ppd`) + +Basis: `TA3505ci.PPD` (Intel-Treiber, Version 8.6006). + +**Entfernt:** +- Alle 11 `*APDialogExtension:`-Zeilen +- `*cupsPreFilter: "application/pdf 0 kyoprefilter_E"` + +**Geändert:** +```diff +- *cupsFilter: "application/vnd.cups-postscript 0 kyofilter_E" ++ *cupsFilter: "application/vnd.cups-postscript 0 kyofilter" +``` + +**KmManagment-Sektion** (ersetzt die alte Liste 00000000–00000030): + +```ppd +*% Kostenstelle (5-stellig) direkt eintragen — keine führenden Nullen nötig. +*% Zeile kopieren und Zahl ersetzen: +*% *KmManagment MG12345/Code 12345: "" +*OpenUI *KmManagment/Job Accounting: PickOne +*DefaultKmManagment: Default +*OrderDependency: 60 AnySetup *KmManagment +*KmManagment Default/Aus: "" +*KmManagment MG12345/Code 12345: "" +*?KmManagment: "" +*End +*CloseUI: *KmManagment +``` + +Der PPD-Wert bleibt leer (`""`), da der Filter die PostScript-Injection übernimmt. + +**Unverändert:** alle anderen Optionen — InputSlot, PageSize, KCStaple, OutputBin, Duplex, Farbe etc. + +## Python CUPS-Filter (`kyofilter`) + +**Installationspfad:** `/usr/libexec/cups/filter/kyofilter` +**Rechte:** 755, root:wheel +**Interpreter:** `/usr/bin/python3` (macOS vorinstalliert) + +**CUPS-Schnittstelle:** +``` +kyofilter <copies> <options> [filename] +``` +- Eingabe: PostScript (stdin oder Datei) +- Ausgabe: PostScript (stdout) +- Logs: stderr → CUPS error_log + +**Logik:** + +1. `argv[5]` parsen → Key=Value-Dict +2. `KmManagment`-Wert lesen +3. Startet mit `MG` und ist numerisch → Code extrahieren, auf 8 Stellen zero-padden +4. Sonst → reiner Passthrough +5. PostScript-Stream zeilenweise lesen: + - Vor `%%EndSetup`: `(XXXXXXXX) statusdict /setmanagementnumber get exec` injizieren + - Alle anderen Zeilen unverändert weiterleiten +6. Fallback: falls kein `%%EndSetup` gefunden → vor erstem `%%Page:` injizieren, Warning ins Log + +**Beispiel:** Kostenstelle `12345` → `(00012345) statusdict /setmanagementnumber get exec` + +## Installer (`.pkg`) + +**Gebaut mit:** `pkgbuild` + Developer ID Installer Zertifikat +**Bundle-ID:** `de.kydriv.driver` + +```bash +pkgbuild \ + --root installer/root \ + --scripts installer/scripts \ + --identifier "de.kydriv.driver" \ + --version "1.0.0" \ + --sign "Developer ID Installer: NAME (TEAM-ID)" \ + kydriv-driver-1.0.0.pkg +``` + +**postinstall-Script:** +```bash +#!/bin/bash +chmod 755 /usr/libexec/cups/filter/kyofilter +chown root:wheel /usr/libexec/cups/filter/kyofilter +launchctl kickstart -k system/org.cups.cupsd +``` + +**Notarisierung** (einmalig pro Release): +```bash +xcrun notarytool submit kydriv-driver-1.0.0.pkg \ + --apple-id EMAIL --team-id TEAM-ID --password APP-PASSWORT --wait +xcrun stapler staple kydriv-driver-1.0.0.pkg +``` + +Notarisierte `.pkg`-Dateien bleiben dauerhaft gültig, auch nach Ablauf des Entwicklerzertifikats. + +## Benutzer-Workflow nach Installation + +1. Kostenstelle in PPD eintragen (einmalig, Texteditor) +2. `.pkg` installieren +3. Drucker in Systemeinstellungen hinzufügen → `TA3505ci_AS.ppd` auswählen +4. Druckdialog → Job Accounting → eigene Kostenstelle wählen +5. Preset speichern +6. Ab sofort: Preset auswählen → drucken + +## Testing + +| Stufe | Methode | Erfolgskriterium | +|-------|---------|-----------------| +| 1 | Filter mit Beispiel-PS über stdin aufrufen | Injection vor `%%EndSetup` im Output | +| 2 | `cupstestppd ppd/TA3505ci_AS.ppd` | Ausgabe: PASS | +| 3 | Manuelle Installation, Testseite drucken | Seite kommt raus | +| 4 | CUPS-Log + Kyocera-Webinterface Job-Log | Kostenstelle korrekt erfasst | +| 5 | `.pkg` auf frischem System installieren | End-to-End-Workflow funktioniert | + +## Offene Fragen / Nächste Schritte + +- Genaue Kostenstellen-Codes für die PPD erfragen und eintragen +- Verifizieren, dass `setmanagementnumber` auf dem 3505ci die Kostenstelle korrekt bucht (Stufe 4) +- Ggf. weitere Kyocera-spezifische PPD-Optionen aus dem alten Treiber übernehmen