Die Auswahl basierte auf den folgenden Anforderungen: MFP ist nicht teuer, kompakt, Netzwerkdruck, Verfügbarkeit von Treibern für Linux (Fedora / Mint / OpenSUSE). Der Held des Artikels besaß all diese Eigenschaften, aber eine Nuance wurde nicht bemerkt. Gebogener Ressourcenzähler. Wenn Sie sich fragen, wie man heilt und
(Memo für Grammatik Nazi von einer Person mit leichter Dysgraphie)
, . . / , . , . «», . , , , / . , , , , . , , . , —
Willkommen zurück!
Die Sache ist,dass der MFP nicht die Menge des verbrauchten Toners zählt, sondern die Anzahl der gedruckten Seiten. Wenn ich die Starterpatrone mit einem ausreichend großen Füllgrad bedruckte, passierte ein Vorfall mit der zweiten. Tatsache ist, dass meine Frau sich schnell der örtlichen Gemeinde Angloms anschloss und ein Teil der Arbeit im Zusammenhang mit der Bereitstellung von Druck auf uns fiel. Alle Arten von Konturbildern zum Schneiden / Färben / Origami sind also mit Toner gefüllt, höchstens 1% des Blattes. Infolgedessen befand ich mich auf der Theke "leer", aber tatsächlich - volle 70 Prozent der Patrone. Nein, ich bin nicht so arm, dass ich es mir nicht leisten kann, ein neues zu kaufen, nicht so umweltbewusst, moralische Qualen zu erleben und ein brauchbares Produkt auf eine Mülldeponie zu werfen, sondern aus dem Gefühl heraus, dass Sie legal übergeben wurden - begann der Stuhl Rauch, der ein Impuls zum Handeln war ...
Ehrlich gesagt hatte ich nicht gehofft, ein "Hacker der Mutter" zu werden, da ein solcher Hardwareschutz sehr schwer zu brechen ist. Zumindest zählte ich auf anständige Verschlüsselungsalgorithmen und OTP-Speicher (einmal programmierbar). Aber die Realität erwies sich als viel alltäglicher. Glücklicherweise gab es viele Anweisungen auf der Anfrage, die Patrone zurückzusetzen, und der " Schutzchip " erwies sich als ein weit verbreitetes I2C-EEPROM AT24C01 , das mit einem minimalen "Bodykit" und nicht mit einer Platine verlötet war. Im Großen und Ganzen können Sie im nächsten Bild den Artikel fertigstellen:
Originalvideo
Mit jedem Programmierer lesen wir den Inhalt der Mikroschaltung, "nullen" die in roten Rahmen umrandeten Zellen und ändern die letzten Ziffern der Seriennummer. Es ist zu beachten, dass die Seriennummer eine Textzeichenfolge ist, die mit einem Leerzeichen endet. Sie müssen sie daher im Bereich 0 ... 9 (0x30 ... 0x39) ändern. Die physikalische Adresse der auf der Platine gelöteten Mikroschaltung lautet 0x03. Aber ... Triff einen Schuhmacher ohne Stiefel. Da es keinen universellen Programmierer gibt, nehmen wir
Zusammengebaut sieht es so aus:
Ich habe die "Schutz" -Karte aus der Patrone entfernt, um sicherzustellen, dass die im Handbuch angegebene Pinbelegung der Realität entspricht, und um die physikalische Adresse des Mikrokreises auf dem Bus zu erhalten:
Kontaktflächen von links nach rechts: GND, + 5V, SCL . SDA.
Sie müssen bei der Herstellung des Adapters nicht klug sein , sondern die Drähte direkt auf die Platine löten, ohne sie aus der Kassette zu entfernen. Als nächstes kopiere meinen beschissenen Code in die Arduino IDE:
Shitcode
#include <stdint.h>
#include <Wire.h>
//----------------------------------------------------------------
#define EERROM_SZ (0x80)
#define EERROM_PHY_ADDR (0x03)
#define EERROM_HEAD (0x50)
#define PRN_BUFF_SZ (0x08)
#define SER_START_ADDR (0x20)
#define SER_END_ADDR (0x2B)
#define SER_MOD_ADDR0 (0x2A)
#define SER_MOD_ADDR1 (0x29)
#define SER_MOD_ADDR2 (0x28)
//----------------------------------------------------------------
static uint8_t eeprom_data[EERROM_SZ];
static bool erased;
static bool z_filled;
//----------------------------------------------------------------
static uint8_t ee_read(uint8_t phy_addr, uint8_t addr)
{
uint8_t res;
Wire.beginTransmission(EERROM_HEAD | phy_addr);
Wire.write(addr);
Wire.endTransmission();
Wire.requestFrom(EERROM_HEAD | phy_addr, 1);
res = Wire.read();
return res;
}
//----------------------------------------------------------------
static void ee_write(uint8_t phy_addr, uint8_t addr, uint8_t data)
{
Wire.beginTransmission(EERROM_HEAD | phy_addr);
Wire.write(addr);
Wire.write(data);
Wire.endTransmission();
delay(5);
}
//----------------------------------------------------------------
static void read_data(uint8_t phy_addr)
{
uint8_t addr;
uint8_t data;
erased = true;
z_filled = true;
Serial.print("Read from phy addr ");
Serial.print(phy_addr);
for (addr = 0; addr < EERROM_SZ; addr++)
{
if (0 == (addr & 0x03))
{
Serial.print(".");
}
data = ee_read(phy_addr, addr);
eeprom_data[addr] = data;
if (0xFF != data)
{
erased = false;
}
if (0x00 != data)
{
z_filled = false;
}
}
Serial.println("Ok");
}
//----------------------------------------------------------------
static void write_data(uint8_t phy_addr)
{
uint8_t addr;
Serial.print("Write to phy addr ");
Serial.print(phy_addr);
for (addr = 0; addr < EERROM_SZ; addr++)
{
if (0 == (addr & 0x03))
{
Serial.print(".");
}
ee_write(phy_addr, addr, eeprom_data[addr]);
}
Serial.println("Ok");
}
//----------------------------------------------------------------
static bool check_data(uint8_t phy_addr)
{
uint8_t addr;
uint8_t data;
Serial.print("Check from phy addr ");
Serial.print(phy_addr);
for (addr = 0; addr < EERROM_SZ; addr++)
{
if (0 == (addr & 0x03))
{
Serial.print(".");
}
data = ee_read(phy_addr, addr);
if (eeprom_data[addr] != data)
{
Serial.println("FAILED");
return false;
}
}
Serial.println("Ok");
return true;
}
//----------------------------------------------------------------
static void print_data(void)
{
uint16_t addr;
char prn_buff[PRN_BUFF_SZ];
for(addr = 0; addr < EERROM_SZ; addr++)
{
if (0x00 == (addr & 0x0F))
{
snprintf(prn_buff, PRN_BUFF_SZ, "%4X: ", addr);
Serial.print(prn_buff);
}
snprintf(prn_buff, PRN_BUFF_SZ, "%2X ", eeprom_data[addr]);
Serial.print(prn_buff);
if (0x0F == (addr & 0x0F))
{
Serial.print("\n\r");
}
}
Serial.print("\n\r");
}
//----------------------------------------------------------------
static void prn_serial(void)
{
Serial.print("Serial #: ");
Serial.write(&eeprom_data[SER_START_ADDR], 1 + SER_END_ADDR - SER_START_ADDR);
Serial.print("\n\r");
}
//----------------------------------------------------------------
static void mod_serial(void)
{
eeprom_data[SER_MOD_ADDR0]++;
if (eeprom_data[SER_MOD_ADDR0] > '9')
{
eeprom_data[SER_MOD_ADDR0] = '2';
}
eeprom_data[SER_MOD_ADDR1]++;
if (eeprom_data[SER_MOD_ADDR1] > '9')
{
eeprom_data[SER_MOD_ADDR1] = '3';
eeprom_data[SER_MOD_ADDR2]++;
if (eeprom_data[SER_MOD_ADDR2] > '9')
{
eeprom_data[SER_MOD_ADDR2] = '1';
}
}
}
//----------------------------------------------------------------
static void reset_mileage(void)
{
uint8_t i;
for (i = 0x12; i <= 0x1F; i++)
{
eeprom_data[i] = 0;
}
for (i = 0x2C; i <= 0x7F; i++)
{
eeprom_data[i] = 0;
}
}
//----------------------------------------------------------------
static bool test_magic(void)
{
if (0x32 != eeprom_data[0]) return false;
if (0x00 != eeprom_data[1]) return false;
if (0x01 != eeprom_data[2]) return false;
if (0x03 != eeprom_data[3]) return false;
return true;
}
//----------------------------------------------------------------
void setup()
{
int key;
Serial.begin(9600);
Wire.begin();
Serial.println("\tSP 150 cartridge mileage resetter");
Serial.println("Connect like this:");
Serial.println(" TOP");
Serial.println("______________________________");
Serial.println("|o |GND| |+5V| |SCL| |SDA| <=");
Serial.println("| |GND| | 5V| | A5| | A4| ");
Serial.println("------------------------------");
Serial.println(" cartridge roller");
Serial.println("\n\r\n\r\tTo start, press 'm' or any button for test (not prog)...\n\r");
do
{
key = Serial.read();
}
while(-1 == key);
#if 0
for (uint8_t paddr = 0; paddr < 8; paddr++)
{
Serial.print("Scan phy ");
Serial.println(paddr);
for (uint8_t i = 0; i < 5; i++)
{
Serial.print("Read from ");
Serial.print(i);
Serial.print(".........");
Serial.println(ee_read(paddr, i));
}
}
return;
#endif
read_data(EERROM_PHY_ADDR);
Serial.println("Read:");
print_data();
if (true == erased)
{
Serial.println("ERROR! The EEPROM is erased or the connection / phy addr is incorrect.");
return;
}
if (true == z_filled)
{
Serial.println("ERROR! The EEPROM is Z filled.");
return;
}
if (false == test_magic())
{
Serial.println("ERROR! Invalid magic number.");
return;
}
prn_serial();
mod_serial();
reset_mileage();
Serial.println("\n\rModified:");
print_data();
prn_serial();
if ('m' != (char)key)
{
Serial.println("WARNING! The data was not modified in the EEPROM");
return;
}
write_data(EERROM_PHY_ADDR);
if (false == check_data(EERROM_PHY_ADDR))
{
return;
}
Serial.println("Fin");
}
void loop()
{
//do nothing
}
(Über den Shit-Code - ja, er wurde weder nach Speicher (alle Daten werden in ein Array eingelesen) noch nach Leistung (Lesen und Schreiben erfolgt byteweise) oder nach Funktionalität optimiert, sondern für eine so einfache Aufgabe - und so geht es!)
Wir flashen Arduinka, öffnen ein beliebiges Terminal (I18n, 9600 Baud), die eingebaute Arduino IDE reicht aus, setzen die Karte zurück, drücken eine beliebige Taste:
Danach wird der Inhalt des EEPROM gelesen, modifiziert, aber nicht geschrieben. Wenn der Vorgang fehlerfrei verlaufen ist, setzen Sie die Karte erneut zurück und drücken Sie m. Danach werden alle Schritte ausgeführt und die geänderten Daten werden geschrieben. Wenn etwas schief gelaufen ist, überprüfen Sie das Diagramm erneut und versuchen Sie es erneut. Nach erfolgreicher Nullung löten wir die Drähte und installieren die Patrone. Der Tonerstand sollte 100% betragen.
Ich entschuldige mich für das "Wasser", die Anweisung von 3 Zeilen - sehr wenig für einen Beitrag. Ich hoffe, die Informationen waren nützlich und auch - der Autor ist nicht verantwortlich für mögliche Schäden an der Ausrüstung, den Entzug des Garantieservices, alles, was Sie tun, geschieht auf eigene Gefahr und Gefahr ...
Ein weiteres Update, ein von meiner Patrone erhaltener Dump:
Read from phy addr 3................................Ok 0: 32 0 1 3 2 1 1 0 0 0 34 30 38 30 31 30 10: 16 5 4D 4D 1 2 11 70 0 0 0 0 14 14 5 21 20: 43 37 30 36 4D 39 30 33 31 39 35 20 0 45 0 0 30: 39 1 0 0 0 0 0 0 3E 4 0 0 0 0 0 0 40: 5 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50: 0 0 0 0 0 0 0 0 14 E 5 1B 14 E 5 1B 60: 0 0 0 0 0 0 0 0 77 2 0 0 0 0 0 0 70: C3 23 2A 0 16 0 0 55 0 0 0 0 0 0 0 0