цифровая электроника
вычислительная техника
встраиваемые системы

 
» » Проводим инженерный анализ принтера Lexmark

Проводим инженерный анализ принтера Lexmark

Автор: Mike(admin) от 22-09-2016, 06:32

Инженерный анализ (он же обратный инжиниринг, он же реверс-инжиниринг, он же reverse engineering) является увлекательным и очень полезным занятием как для новичков, так и для профессионалов в электротехнике. Его суть заключается в исследовании определенного устройства или оборудования для того, чтобы понять его принцип действия. Практиковаться в инженерном анализе следует всем, кто хочет добиться в своей инженерной профессии большего и укрепить аналитический склад ума.


Проводим инженерный анализ принтера Lexmark

В данном материале будет показан пример инженерного анализа принтера Lexmark Pro 805, как достаточно интересного экземпляра офисной техники, который можно относительно легко разобрать. Помимо этого, плюсом Lexmark является то, что его прошивка полностью обновляема. Ее легко открыть и дизассемблировать. Скачать прошивку можно с официального сайта компании. Кроме того, процессорная архитектура в этом принтере основана на популярном ядре ARM.


Следует помнить, что разбирать принтер стоит, если он находится в нерабочем состоянии, или вы имеете инженерную специальность и полностью отдаете себе отчет в том, что вы делаете. Если же вы не специалист и вам нужно просто отремонтировать устройство или заправить картридж принтера Lexmark, то лучше обратиться к профессионалам, которых можно найти, например, вот здесь.


Итак, первым делом рассмотрим материнскую плату принтера. Она показана на изображении ниже вместе с периферийными компонентами. Как мы видим, будучи вне корпуса эта электронная система все равно работает, что говорит о высоком качестве принтера. Но в таком виде она требует дуплексный модуль (duplex module). К сожалению, датчик наличия дуплексного модуля обойти не удается.


Проводим инженерный анализ принтера Lexmark

Для того чтобы «связаться» с электроникой принтера, желательно найти порт последовательной передачи данных. К счастью на материнской плате есть микросхема 25l6405dmi-12G с последовательным интерфейсом SPI. К этому интерфейсу можно подключить логический анализатор и посмотреть, что происходит.


Проводим инженерный анализ принтера Lexmark

Такая картина мало что поясняет. Поэтому для лучшего понимания ситуации следует подключиться к этому порту SPI с помощью платы Arduino. Изучив документацию на микросхему 25l6405dmi-12G, можно написать код для Arduino, который приведен в приложении в конце материала. А вот так выглядит подключение платы Arduino к материнской плате принтера Lexmark.


Проводим инженерный анализ принтера Lexmark

В конечном итоге можно получить дамп загрузчика. Выглядит он следующим образом:


Проводим инженерный анализ принтера Lexmark

К сожалению, получение дампа загрузчика представляет собой долгий процесс, и при скорости передачи данных 9600 бод это может занять примерно три часа.


Тем не менее, обратный инжиниринг принтера Lexmark получился довольно увлекательным, и опытный программист встраиваемых систем сможет извлечь пользу из данных загрузчика и заставить принтер работать по своему усмотрению.





#define DATAOUT 11 // MOSI
#define DATAIN 12 // MISO 
#define SPICLOCK 13 // sck
#define SLAVESELECT 10 // ss

// Command Definitions
#define WREN 0x06 // Sets the (WEL) write enable latch bit
#define WRDI 0x04 // Reset the (WEL) write enable latch bit
#define RDID 0x9F // Output the manufacturer ID and 2-byte device ID (outputs 3 bytes)
#define RDSR 0x05 // To read out the status register (outputs 1 byte)
#define WRSR 0x01 // To write new values to the status register
#define READ 0x03 // N bytes read out until CS# goes high (requires input address of 3 bytes) (outputs ? bytes)
#define FAST_READ 0x0B // (requires input address of 3 bytes, optional fourth?) (outputs ? bytes)
#define PARALLEL_MODE 0x55 // Enter and stay in parallel mode until power off
#define SE 0x20 // Sector erase (input 3 bytes address)
#define SE_ALT 0xD8 
#define CE 0x60 // Chip erase
#define CE_ALT 0xC7
#define PP 0x02 // Page Program (input 3 byte address)
#define DP 0xB9 // Deep Power Down
#define EN4K 0xB5 // Enter 4Kb sector
#define EX4K 0xB5 // Exit 4Kb sector
#define RDP 0xAB // Release from deep power down
#define RES 0xAB // Read electronic id (optional 3 byte input?)
#define REMS 0x90 // Read electronic manufacturer & device id (2 byte optional? third byte if 0 will 
                   // output manufacturer id first, 1 will output device id first)


char fmt[16]; // Some place to sprintf into
byte eeprom_output_data = 0;
byte eeprom_input_data = 0;
byte clr = 0;

byte spi_transfer(volatile byte data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1 << SPIF)))   // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void setup()
{
  Serial.begin(9600);

  pinMode(DATAOUT     , OUTPUT);
  pinMode(DATAIN      , INPUT);
  pinMode(SPICLOCK    , OUTPUT);
  pinMode(SLAVESELECT , OUTPUT);
  
  // Data sheet says this must be high
  digitalWrite(SLAVESELECT, HIGH);
  
  // SPCR = 01010000
  //interrupt disabled, spi enabled, msb 1st, master, clk low when idle,
  //sample on leading edge of clk, system clock/4 rate (fastest)
  SPCR = (1 << SPE)|(1 << MSTR);
  clr = SPSR;
  clr = SPDR;

  delay(1000);
}

void ReadID() {
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(RDID);
  
  int b1 = spi_transfer(0xFF);
  int b2 = spi_transfer(0xFF);
  int b3 = spi_transfer(0xFF);
  
  digitalWrite(SLAVESELECT, HIGH);
  
  sprintf(fmt, "%02X %02X %02X\n", b1, b2, b3);
  Serial.print(fmt);
}

void ReadElectronicId() {
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(RES);
  
  spi_transfer(0x00);
  spi_transfer(0x00);
  spi_transfer(0x00);
  
  int b1 = spi_transfer(0xFF);
  
  digitalWrite(SLAVESELECT, HIGH);
  
  sprintf(fmt, "%02X\n", b1);
  Serial.print(fmt);
}

void ReadManufactureId() {
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(REMS);
  
  spi_transfer(0x00);
  spi_transfer(0x00);
  spi_transfer(0x00);
  
  int b1 = spi_transfer(0xFF);
  int b2 = spi_transfer(0xFF);
  int b3 = spi_transfer(0xFF);
  
  digitalWrite(SLAVESELECT, HIGH);
  
  sprintf(fmt, "%02X %02X %02X\n", b1, b2, b3);
  Serial.print(fmt);
}

void ReadStatusReg() {
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(RDSR);
  
  int b1 = spi_transfer(0xFF);
  
  digitalWrite(SLAVESELECT, HIGH);
  
  sprintf(fmt, "%02X\n", b1);
  Serial.print(fmt);
}

void Dump() {
  int data;
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(READ); // Address auto increments so only need to do a read instruction once
  
  // Address 0x000000
  spi_transfer(0x00);
  spi_transfer(0x00);
  spi_transfer(0x00);
  
  for (int i = 0, x = 0; i < 4096; i++, x++) {
    if (x >= 16) {
      Serial.print('\n');
      x = 0;
    }
    
    sprintf(fmt, "%02X ", spi_transfer(0xFF));
    Serial.print(fmt);
  }
  
  digitalWrite(SLAVESELECT, HIGH);
}

void loop()
{
  ReadID(); // RDID
  //ReadElectronicId(); // RES
  //ReadManufactureId(); // REMS
  //Dump();
  
  while (1) {
    delay(1000);
  }
}



Теги: картриджи



Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий