選択は次の要件に基づいていました:MFPは高価ではなく、コンパクトで、ネットワーク印刷、Linux用のドライバーの可用性(Fedora / Mint / OpenSUSE)。記事の主人公はこれらすべての特徴を持っていましたが、1つのニュアンスは気づかれませんでした。湾曲したリソースカウンター。あなたがどのように治療するのか疑問に思ったら
(軽度の書字障害のある人からの文法ナチのメモ)
, . . / , . , . «», . , , , / . , , , , . , , . , —
ようこそ!
事は、MFPは使用済みトナーの量ではなく、印刷されたページ数をカウントします。スターターカートリッジを十分に充填して印刷すると、2番目のカートリッジにインシデントが発生しました。事実、私の妻はすぐにアングロムの地域社会に加わり、印刷の提供に関連する仕事の一部が私たちに降りかかったのです。そのため、カット/カラーリング/折り紙用のあらゆる種類の輪郭画像には、最大でシートの1%のトナーが充填されています。その結果、私は自分がカウンターで「空」であることに気づきましたが、実際には、カートリッジの70%がいっぱいでした。いいえ、私は新しいものを買う余裕がないほど貧しくはなく、道徳的な苦痛を経験するほど環境的に教育されておらず、有用な製品を埋め立て地に捨てていますが、あなたが合法的に投げ出されたという感覚から-椅子は行動への衝動だった煙...
正直なところ、このようなハードウェア保護を破ることは非常に難しいため、私は「母親のハッカー」になることを望んでいませんでした。私は少なくとも、まともな暗号化アルゴリズムとOTPメモリ(一度プログラム可能)を頼りにしました。しかし、現実ははるかにありふれたものであることが判明しました。幸いなことに、カートリッジのリセット要求には多くの指示があり、「保護チップ」は、ボードではなく最小限の「ボディキット」ではんだ付けされた非常に普及したI2C EEPROMAT24C01であることが判明しました 。概して、次の写真では、記事を完成させることができます:
元のビデオ
どのプログラマーでも、マイクロサーキットの内容を読み取り、赤いフレームで囲まれたセルを「ゼロ」にして、シリアル番号の最後の数桁を変更します。シリアルはスペースで終わるテキスト文字列であるため、0〜9(0x30〜0x39)の範囲で変更する必要があることに注意してください。ボードにはんだ付けされたマイクロ回路の物理アドレスは0x03です。しかし...ブーツのない靴屋に会いましょう。ユニバーサルプログラマーがいないので、
組み立てると次のようになります。
カートリッジから「保護」ボードを取り外して、マニュアルに記載されているピン配置が現実に対応していることを確認し、バス上のマイクロ回路の物理アドレスを取得しました。
コンタクトパッド、左から右へ:GND、+ 5V、SCL 。SDA。 アダプターの製造に
精通している必要はありませんが、カートリッジからワイヤーを取り外さずに、ワイヤーをボードに直接はんだ付けします。次に、私のくだらないコードをArduinoIDEにコピーします。
シットコード
#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
}
(たわごとコードについて-はい、メモリ(すべてのデータが配列に読み込まれる)、パフォーマンス(読み取りと書き込みはバイトごとに実行される)、または機能によって最適化されませんでしたが、そのような単純なタスクのために- Arduinka
をフラッシュし、任意の端末(I18n、9600バイト)を開くと、組み込みのArduino IDEが実行し、ボードをリセットし、任意のボタンを押します。
その後、EEPROMの内容が読み取られます。変更されましたが、書かれていません。手順がエラーなしで進行した場合は、ボードを再度リセットし、mを押します。その後、すべての手順が実行され、変更されたデータが書き込まれます。問題が発生した場合は、図をもう一度確認して、再試行してください。ゼロ調整に成功したら、ワイヤーをはんだ付けし、カートリッジを所定の位置に取り付けます。トナーレベルは100%である必要があります。
「水」、 3行の指示をお詫びします-投稿にはほとんどありません。情報がお役に立てば幸いです。また、作成者は機器の損傷、保証サービスの剥奪について責任を負いません。あなたが行うことはすべてあなた自身の危険とリスクにさらされます...
別の更新、私のカートリッジから受け取ったダンプ:
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