[sane-devel] Brother MFC

Dmitri Katchalov dmitrik@MailAndNews.com
Wed, 22 Aug 2001 12:12:43 -0400

Hi sane people,

I want to write a backend driver for my Brother MFC 4600 
multi-function centre. The idea is to be able to use it over 
the network.

I wonder if someone can suggest me a good starting point.
I'm relatively new to Linux so any resources, web sites, 
mailing lists, tutorials, driver examples etc will be helpful.
Also maybe a place where I can find volunteers to test my 
stuff eventually.

The device is a windows-only phone/fax/printer/scanner/copier. 
It's a typical workhorse fax machine retrofitted with computer connection. 
It comes in USB and parallel flavours. I have the parallel one.

Normally the chances of re-engineering things like that are slim.
Luckily I have discovered a couple of INI file settings in windows 
drivers that enable log files. These log files conveniently show 
function names with parameter values including full hex dump of 
data buffers. I did a few experiments and now I believe I know 
enough about the protocol to start coding.

I included the description of the protocol below. It turned out
to be pretty simple. Please tell me if it looks familiar.

*** The protocol ***
There are in fact two protocols involved:
One is a low-level protocol to provide multiple logical channels
over a single parallel port connection. Each channel has a name, 
can be independently opened, closed and flow-controlled.
Multiple channels can run simultaneously. This low-level protocol 
is specific to parallel port version. I won't go into details but 
I have pretty good idea how it works.

Hi-level scanner protocol runs over the "SCN" logical channel.
The client opens a channel, sends a single request packet, receives 
one or more reply packets then closes the channel.

Here is a typical request packet captured from the log file:
0000:1B 58 0A 52 3D 32 30 30 - 2C 31 30 30 0A 4D 3D 54 :.X.R=200,100.M=T
0010:45 58 54 0A 43 3D 52 4C - 45 4E 47 54 48 0A 42 3D :EXT.C=RLENGTH.B=
0020:37 30 0A 4E 3D 35 30 0A - 55 3D 4F 46 46 0A 41 3D :70.N=50.U=OFF.A=
0030:30 2C 30 2C 31 36 34 38 - 2C 31 31 33 37 0A 80    :0,0,1648,1137.

<ESC>X<CR>     -- always present
R=200,200<CR>  -- resolution, valid values "100,200", "200,200", "400,200"
M=TEXT<CR>     -- scan mode, valid values TEXT, GRAY64, ERRDIF
C=RLENGTH<CR>  -- compression, always RLENGTH, see below
B=50<CR>       -- brightness 0..100, default 50
N=50<CR>       -- contrast 0..100, default 50
U=OFF<CR>      -- no ideas. It's always off
A=0,0,1648,1137<CR> -- scan area in pixels (left,top,right,bottom) 
\x80           -- End-of-data or "Go" command ???

Reply: 1 or more records in the following format:
<1 byte code> [<2 bytes count LSB first> <count bytes of data>]

Known codes:
0x40 - uncompressed scanline data follows
0x42 - RLE compressed scanline data follows
0x80 - End of data
0xC2 - Error "no document"

RLE compression:
  x = get_byte
  if( x <= 0x80 ) { copy next x+1 bytes literally }
  else            { repeat next byte 257-x times  }

Image format: progressive left-to-right top-to-bottom
Left and right are always rounded to the multiple of 16 in request.
The number of scanlines returned may be less than requested 
depending on the physical size of the document.

TEXT:   1 bit/pixel MSB first, 0 is white, 1 is black
ERRDIF: same as above but the scanner does error diffusion.
GRAY64: 1 byte per pixel, 0 is black, 0xFF is white.
In this mode the scanner sends additional 8 scanlines of near 
white then 8 scanlines of near black before the actual image data.
I guess this is for calibration.

Sorry for the long post, I just wanted to use this opportunity
to preserve my finding for posterity :)