Reverse-Engineered Minolta Printer Protocol
WARNING: Everything here was reverse-engineered by hairy folks
on the net, and hence may cause your printer or spouse to
spontaniously explode. We have no relationship to Minolta
other than satisfied customers.
Protocol Basics
The 2400W does not speak PostScript, or anything like it.
It speaks its own totally proprietary protocol, which luckily
was very similar to the protocol spoken by the 2300W,
1200, 1250, 1300, and 1350. I tried to maintain backward compatability
in my driver, so min00 may work with any of these printers,
but I don't have anything but the 2400W to test with (reports welcome!).
The foomatic stuff is currently hardcoded for the 2400W,
since I can't figure out how to pass the right command-line option in
(e.g., "-m 2300W" for the 2300W).
This Minolta format consists of "esc-commands", which always have a
header consisting of 7 bytes, plus at least 1 byte of command data:
- The escape byte 0x1B.
- CMD: a "command byte". See command types listed below.
- A command count byte. This is a counter that starts at 0 for
the file's first command, and increases by 1 for each command thereafter.
- LEN: a two-byte packet data length, in little-endian format.
- CMD^0xff: The command byte again, but with the bits inverted 0-1.
- LEN bytes of arbitrary packet data, interpreted by the command.
- A checksum, computed as the mod-256 sum of everything sent so far
including the escape byte.
Known CMD command bytes include:
- CMD==0x40: Model command. LEN==2 bytes of packet data, giving the
intended printer model number. 0x81 0x00 is the Minolta 1200W/1250W.
0x82 0x10 is the Minolta 2300W. 0x83 0x00 is the Minolta 1300W/1350W.
0x85 0x10 is the Minolta 2400W. Could the second byte mean "color capable?".
If you pass the wrong model number, the printer enters a
"yellow flashing light" mode and must be power-cycled.
- CMD==0x50: Start job command (see "send_start_job"). Always LEN==8 bytes of packet data, but
the function of many bytes is not understood completely:
- Byte 0 seems to select the vertical resolution: 0x00 is 300dpi (not supported on the 2400W?), 0x01 is 600dpi, and 0x02 is 1200dpi (not supported on the 2400W?).
- Byte 1 selects the horizontal resolution, as a multiple of the vertical resolution. 0x00 means same as vertical, 0x01 means twice vertical (e.g., 600dpi vertical by 1200dpi horizontal), 0x02 means four times vertical resolution (only on the 2400W?).
- Byte 2 has no known function and is always zero.
- Byte 3 selects the paper type. Normal is 0x00; transparency is 0x02; see "struct map ptypes" for other options.
- Byte 4 is always 0x00 on the 2400W, and 0x04 on other printers. This might have something to do with line interleave.
- Remaining bytes in packet seem to be zero.
Further ideas or experimental results on these bytes would be quite welcome!
- CMD==0x51: Start page command (see "send_new_page"). For black and white models, there are LEN==22 bytes of
packet data. For color models, there are LEN==28 bytes of packet data.
The function of almost everything is mysterious here.
- Byte 0 is 0 for most printers. For the 2400W, it's 0xF0 for a color page, or 0x80 for a black and white page.
- Byte 1 is always 0x01.
- Bytes 2-3 are a little-endian pixel x coordinate start (normally 0).
- Bytes 4-5 are a little-endian pixel x coordinate end (normally the number of horizontal pixels)
- Bytes 6-7 are a little-endian pixel y coordinate start (normally 0).
- Bytes 8-9 are a little-endian pixel y coordinate end (normally the number of vertical pixels)
- Bytes 10 and 12 are 0x08 for black-and-white pages, 0x20 for color pages.
- Byte 14 gives the paper tray source (see "").
- Byte 15 gives the paper size code (see "").
- Byte 20 is 0xc0 for 300dpi printing (?).
- Byte 24 is 1 for the 2300W, but no other model.
- All other bytes seem to be zero.
Further ideas or experimental results on these bytes would be quite welcome!
- CMD==0x52: Raster data. For black and white, LEN==6 bytes.
For color, LEN==8 bytes. In either case,
the real compressed raster data comes *after* the command checksum.
Format for
Minolta 2400W consists of a 32-bit little-endian raster data byte count,
a color band byte (0x03==Yellow, 0x02==Magenta, 0x01==Cyan, 0x00=Black),
a 1-based packet count within the band, a funky "stop" byte that's normally
0x1c, except the last packet within the band is 0x1e, and a byte
band count "0x03". The raster data compression is described in
the next section. This command is repeated for each chunk of raster data
in each plate until the whole page is ready.
- CMD==0x55: End page. Contains LEN==1 byte of zero data.
This is an important code! Otherwise you go into yellow flashing
mode.
- CMD==0x41: End job. Contains LEN==1 byte of zero data.
For some reason, the raster data is divided into 8 separate "raster data"
chunks for each output plate. It's not clear if this is a hardware
requirement, or just superstition based on the Windows driver.
Image Encoding
What the printer wants is actually quite simple--the engine
just needs a full-page 1200x600 bitmap per page. For color, you just
send a separate bitmap for Yellow, Magenta, Cyan, and Black
toner (in that funky order). Luckily, with Foomatic the production
of this bitmap is handled by GhostScript, and min00 (a Foomatic
"filter") is passed in fully-rasterized PBM images of each page,
just "cat"'d together into one long stream. For color, the page
images are passed in from ghostscript in "pksmraw" format, which
seems to just be Cyan, Magenta, Yellow, and Black (note the order)
PBM images catted together.
The only complexity is that the printer encodes the page bitmaps
using a clever but bizarre run-length encoding scheme. The image pixels
are stored in the PBM or output image as bits (1 for white; 0 for black/toner).
But the image data is then run-length encoded as bytes; hence taking
8 adjacent pixels at once.
The run-length encoding used is funky. You send data one row at a time.
Each row of data starts with a start byte and a table with up to
16 entries of pixel bytes. The start byte
is equal to the number of table entries plus 0x80, and the table entries
are used in the "table data" compression scheme below. The remaining data
is encoded as:
- Byte from 0xc1-0xff: long-repeated byte. The low 6 bits of the
byte give the number of 64-fold repetitions of the following byte.
E.g., "0xc2 0x77" means to repeat the pixel 0x77 a total
of 2*64=128 times.
- Byte from 0x81-0xbf: short-repeated byte. The low 6 bits give
the number of pixel repetitions of the following byte. E.g., "0x82
0x77" means to repeat the pixel "0x77" twice.
- Byte from 0x41-0x7f: table data. The number of following bytes of table
data to follow is the byte-0x3F. Each byte corresponds to two output
pixels: the high 4 bits give the left pixel's table index, the low 4 bits
give the right pixel's table index. E.g., "0x41 0x56 0x78" means to output
4 pixels from table indices 5, 6, 7, and 8.
- Byte from 0x01-0x40: uncompressed data. The number of uncompressed
bytes of pixel data is the byte plus 1. E.g., "0x02" means the next 3
bytes are raw uncompressed pixel data.
I don't know what bytes 0x00, 0x40, 0x80, or 0xc0 do. Possibly nothing.
For the 2400W, the default mode seems to compress "interleaved" scanlines,
made of alternating bytes from two adjacent input scanlines. For example,
input scanlines "0xa1 0xa2 0xa3" and "0xb1 0xb2 0xb3" would be compressed
as a single double-width scanline "0xa1 0xb1 0xa2 0xb2 0xa3 0xb3".
I'm not clear whether other printers also support this interleaved mode,
or if it's possible to turn off interleaved mode for the 2400W, possibly
via some wierd CMD byte above.
The min00 driver includes a rough little utility
called "min_decode.c" that takes a Minolta esc-file and produces a
PPM output image. It dumps out the various esc-headers it encounters,
and creates an output image. See "min00/test/README.txt" for an example
of how to use min_decode. You should be able to run this program on any
output file from any comparable Minolta driver, or even the .prn files
from the Windows driver (from "Save to file" in the print dialog box).
Back to min00 driver main page
Orion Lawlor,
olawlor@acm.org