Vor ein paar Tagen fand ich bei eBay-Kleinanzeigen einen (wirklich unglaublich) günstigen Laserdrucker. Da mein alter wirklich alt ist und auch dementsprechend schlecht und langsam druckt, war as längst überfällig. Natürlich gab es einen Haken an der 5€ Geschichte... der Toner ist (fast) leer, zumindest soweit, dass er ganz einfach nicht mehr drucken möchte. Ich kannte das Verhalten schon von meinem alten Brother, hier war es aber noch ziemlich einfach das System zu umgehen - man musste nur ein kleines Sichtfenster am Toner abkleben, so dass die Sensorik von einem entsprechend hohen Füllstand ausgeht. Interessanterweise gibt es bei dem Schnäppchen-Drucker so etwas nicht, dafür aber Kontakte zu einem Chip direkt im Toner.

Okay, es macht zwar keinen Sinn einen Füllstand-Sensor in einem Verbrauchsgegenstand wie der Tonerkartusche selbst zu verbauen, aber irgendwoher muss der Drucker ja wissen ob die Kartusche denn nun leer ist oder nicht, und schließlich deuten die Kontakte auf irgendeine Art der Kommunikation zwischen Drucker und Kartusche hin - es wäre daher naheliegend (wenn auch aus den genannten Gründen nicht unbedingt wirtschaftlich) dass der Drucker die Kartusche dazu veranlasst, den Füllstand zu messen, und diesen dann an den Drucker zurückzumelden. Aber irgendwie... so ganz macht das trotzdem keinen Sinn.

Schauen wir uns doch den Toner, bzw. den daran installierten Chip etwas genauer an.

#Bild vom ausgebauten Chip

Merkwürdig, woher soll der Drucker - oder die Kartusche - denn ohne Signalleitungen zu einem Sensor über den Füllstand Bescheid wissen? Etwa kabellos? Müsste dann der Sensor nicht zumindest mit einer Spannung versorgt werden?

Software ist günstiger als Hardware

Alles sehr merkwürdig... aber langsam drängt sich der Verdacht auf dass es gar keinen Sensor gibt, sondern der Drucker den Füllstand lediglich abschätzt. Durch eine solche softwarebasierende Füllstandserkennung würde sich der Hersteller natürlich laufende Kosten bei der Herstellung der Kartuschen sparen, einmal programmiert und immer wieder verwenden. Der Chip wäre dann nur eine Art Personalausweis, mit dem sich die Kartusche beim Drucker identifiziert, so erfährt der Drucker z.B. von der ursprünglichen Kapazität (d.h. wieviel Toner war im Originalzustand vorhanden). Natürlich muss sich der Drucker auch irgendwie merken welcher Toner welchen Füllstand hat, oder aber diese Information wird ebenfalls auf dem Chip gespeichert.

Das Toner-Gedächtnis

Wir wollen erst einmal davon ausgehen dass die Information über den Füllstand der einzelnen Kartuschen irgendwo im Drucker selbst gespeichert werden. Die Annahme ist generell nicht ganz sinnvoll, da sich damit automatisch ein Limit ergeben würde, wie oft man einen neuen Toner einsetzen kann - oder aber alte, lang zurück liegende Informationen werden überschrieben. Letzeres wäre natürlich eine Freude, denn dann müsste man dem Drucker nur so lange neue Kartuschen einsetzen, bis er vergessen hat wie voll die eigentlich wichtige war. Dazu würde man sicherlich keine Wagenladung neuer Toner benötigen, ich denke hier eher an eine Art Simulation mittels Arduino o.ä.

Auch wenn sich die Annahme als nicht ganz sinnvoll erweist, wollen wir doch einmal die Hauptplatine des Druckers inspizieren. Nicht alles was der gesunde Menschenverstand als unsinnig erachtet ist auch tatsächlich so und es wäre wirklich angenehm, wenn es denn so wäre.

# Bild der Platine

Tatsächlich findet sich auf der Platine ein kleiner, verdächtig aussehender Chip. Wenn wir die Bezeichnung googeln finden wir schnell heraus dass es sich dabei um einen kleinen nicht-flüchtigen Speicher handelt (EEPROM). Was muss sich ein Drucker denn schon Langzeitgedächtnis merken? Wenn dann doch seine Seriennummer, die MAC-Adresse und - ja - auch den Füllstand des Toners.

Wir finden also im Internet den genannten Chip, und ein Blick ins Datenblatt verrät auch wie er denn angeseuert wird. Das Protokoll nennt sich SPI und ist weit verbreitet. Wie genau finden wir nun heraus was sich auf dem Chip befindet?

Wo ist Walter?

Da wir keinen Einblick haben was genau die Daten im EEPROM bedeuten, haben wir ganz allgemein zwei Möglichkeiten. Entweder wir lesen den gesamten Speicher aus, verändern irgendetwas am System (wir drucken z.B. etwas aus) und vergleichen schließlich den aktuellen mit dem vorherigen Stand - oder aber, wir hängen uns direkt in die Kommunikation zwischen Hauptprozessor und EEPROM - mit einem Logic Sniffer etwa.

Ich habe mich für die erste Variante entschieden, auch weil diese teilweise schon erfolgreich von anderen im weiten Netz getestet wurde (wenn auch an ganz anderen Druckern). Wir müssen also das EEPROM bitten uns seine Geheimnisse zu offenbaren, dazu müssen wir natürlich mit ihm kommunizieren, wie genau - das steht im Datenblatt.

Als Master, der dem EEPROM sagt was es auszuspucken hat, habe ich mir einen Arduino MEGA 2560 ausgesucht, ein kleinerer Kollege hätte es sicher auch getan, aber was solls. Ein paar Zeilen Code und filigrane Lötarbeiten später sieht mein Drucker nun aus wie Franksteins Monster...

# Bild vom Aufbau
# Sketch vom Arduino

Wie bereits erwähnt sieht der Ablauf nun folgendermaßen aus:

  1. EEPROM vollständig auslesen
  2. Eine Seite drucken
  3. EEPROM erneut auslesen

Es bietet sich an eine Testseite zu drucken, das geht auch wenn der Toner laut Drucker leer ist, komisch oder? Dazu drücken wir die Taste mit dem roten geometischen Gebilde mehrere Sekunden.

Mittels KDiff3 oder einem ähnlichen diff utility lässt sich relativ leicht herausfinden wo sich durch den Druck der Testseite Werte geändert haben. Tatsächlich sind es nur drei Stellen. Wer die Testseite ein wenig genauer betrachtet findet etwa einen Wert der sich Total Page Count nennt. Aha, der Drucker merkt sich also auch wieviele Seiten insgesamt gedruckt wurden. Zumindest dieser Wert kann doch nur auf dem EEPROM gespeichert sein. Tatsächlich entspricht die dort aufgeführte Zahl den Werten der Bytes ... todo ... .

Bäumchen wechsle dich

Also los, setzen wir doch einfach mal die Bytes auf 0 in unserer lokalen Kopie es Speicherinhalts des EEPROM und laden es hoch, natürlich wieder mittels Arduino. Eine Testseite gedruckt und... tadaaaa!

# Bild vorher - total page count
# Bild nachher - total page count

Naja, das bringt uns zwar nichts aber ist zumindest irgendwie nett anzusehen :D Also was bedeuten nun die anderen zwei Blöcke die sich beim Druck einer Seite ändern? Keine Ahnung! Ich hoffe dass einer davon die Tonerwerte enthält... Also probieren wir's doch einfach mal aus. Wir setzen auch die anderen auf 0 und drucken erneut eine Testseite.

Leider hat sich nicht viel getan, ja eigentlich garnichts! Und wenn wir das EEPROM sicherheitshalber erneut auslesen merken wir auch warum. Die Werte die wir zuvor noch auf 0 gesetzt haben sind schon wieder mit anderen Werte überschrieben... Tja, dann sind die Füllstände wohl doch auf dem Chip an der Kartusche. Mal sehen...

Open Logic Sniffer und Buspirate

Wir schauen uns den Chip nochmal genauer an. Es sind 4 Kontakte, zwei davon sind natürlich die Spannungsversorgung (Vcc und GND). Die anderen beiden sind vermutlich irgendein Bussystem, nur welches? Ist es etwa I²C, oder vielleicht irgendein Samsung-spezifisches? Zum Glück gibt es da dieses kleine FPGA Board mit dem Namen Open Workbench Logic Sniffer. Kurzerhand angeschlossen und einfach erneut eine Seite drucken!

# Bild vom Anschluss am Bus

Leider ist die Software zum OLS wirklich nicht besonders toll (es gibt eine Alternative: Sigrok). Wie dem auch sei, es stellt sich heraus (nach viel Sucherei bezüglich der Triggereinstellungen) dass es tatsächlich I²C ist! Das ist auch gleichzeitig das Problem beim Open Logic Sniffer, er speichert das Sampling lokal ab und überträgt diese erst danach an den PC. Durch den begrenzten Speicher verpasst man so gerne relevante Kommunikation die vielleicht erst später stattfindet. Abhilfe schaffen hier "on-the-fly" Logic-Sniffer, wie z.B. das bekannte Gerät von Salea oder die günstigen, FX2-basierten Nachbauten.

Also wie gesagt: I2C. Die Kommunikation zwischen Chip (Slave) und Drucker (Master) sieht bei einem Druck einer Testseite folgendermaßen aus:

Page-Count: 03

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 10 B7 77 58 F8 7D CC 43 77 2E 28 F5 AC 70 B0 C3 82 49

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 28 8A 3E F2 0C A6 FD 45 91 47 A4 59 B9 7C DB A8 34 DB 85 2B 17 B1 43 DC 6E BD B0 74 40 97 B2 22 90 00 59

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 B9 C0 F9 04 90 71 A4 A7 B0 3E C2 A5 6F 8A 4F 26 49 FE 83 EE B1 9D 98 AC BB

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 10 B4 6A 24 6A 0F CC 1F F0 1B E0 70 F6 93 D9 B5 1D 51

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 5C 5C E8 A1 71 CF 7D 57 EB AA 41 DB CC 9F C6 28 90 00 2B

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 3C 61 22 65 63 9B 43 0F 2F 82 03 3B AC 69 4D 53 81 D3 E5 41 16 87 92 1A 75

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 E6 C3 21 87 AE 78 FB 88 B2 FD C9 A2 F2 10 39 15 B3 0D 78 AD C3 F9 DE 2C 15

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

Page-Count: 13

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 10 EA 70 40 A4 8A 33 B6 79 C9 71 11 52 D8 4D 05 3D 2C

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 35 CA 14 8F D8 01 72 2E 9E D7 33 CE 0D 03 49 D3 FB 35 FF E5 F1 69 D0 C8 CE 02 CE 07 E5 B0 82 BB 90 00 6C

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 25 4F BA 4A EC C7 9C 55 55 E6 3B 06 0A B1 E0 29 5A 3C 96 08 A8 E0 A1 2A C5

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 10 02 8F 0A 7F 53 40 A6 CB 4C F4 55 41 94 2F 0F B3 5F

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 86 8B DE 1C 64 F1 AD 00 94 7F 50 48 B7 0E 60 6A 90 00 27

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 96 79 18 9E 77 C9 7D F4 53 90 FC E7 62 82 97 2B B7 D2 3F 6F 9F AC A1 14 13

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

i2c-1: Write
i2c-1: Address write: 50
i2c-1: Data write: A4 C6 00 00 18 46 CF 7E 2C 49 4A 69 7C 51 12 87 34 35 E5 22 58 5D 84 41 1C 5B 15 9C E9 52

i2c-1: Read
i2c-1: Address read: 51
i2c-1: Data read: 90 00 90

... to be continued ...

Besucher-Aktionen

Besucher-Aktionen

Ich freue mich über einen Kommentar! Das geht auch als Gast: mit Disqus einloggen » als Gast.