==============================================================================
A4 Tech AC 4096 handheld scanner driver  version 0.1
==============================================================================

This is the application-developer's guideline for using the ioctl-interface.
It has been taken from the logi32.o driver, written by Andreas Beck with
his kindly permission.

==============================================================================
LOGITECH SCANMAN+ 400 dpi handheld scanner driver  version 0.0.2
==============================================================================

Hi folks!

This is a driver for the LOGITECH SCANMAN+ scanner driven thru its own 
interface board.

This is the application-developer's guideline for using the ioctl-interface
provided by logi32.o.

Any suggestions are welcome and I would appreciate feedback from other 
scanner device driver writers to be able to create a common interface.

Please note,that as this is version 0.0.2 the definitions stated here may be
changed frequently,as the driver develops.

I have to admit,that I never designed a ioctl-interface to a scanner or any
similar device before,so please tell me,if there is something wrong with
my approach and what could be done better.

If you've written a nice scanning program using this ioctl-api, please drop 
me a line also.

So these are the supported ioctl functions:

**********************************************************************
#define HSIOCGSCC               0x73e8  /* Get Scanner Capabilities */
**********************************************************************

[Please note that the MAGIC NUMBERS of the ioctls are likely to change in
 the near future when the ioctl-specification gets more stable and the
 "major clean up" occurs]
This is the most important of the scanner system calls,as it provides nearly
all the necessary information on how to access the scanner and what is
supported.

This function will return the following structure :

struct scanner_capabilities {

	int o_scm_mono;		/* Options for monochrome mode */
	int o_scm_grey;		/* Options for greyscale  mode */
	int o_scm_true;		/* Options for true-color mode */

	int o_xdpi;		/* Options for x resolution */
	int o_ydpi;		/* Options for y resolution */

	int o_bright;		/* Options for brightness */
	struct minmax bright;
	int o_contrast;		/* Options for contrast */
	struct minmax contrast;
	int o_hue;		/* Options for hue */
	struct minmax hue;
	int o_sat;		/* Options for saturation */
	struct minmax sat;

	int phys_width;		/* Width in mm */
	int phys_length;	/* Length in mm */

	int av_options;		/* Number of available Options (0-32) */

};

All 'o_'-prefixed fields are "option-fields" which can contain a combination 
of the following flags (i.e this is a bitfield):

#define SCC_SOFTSELECT  0x0001  /* Option is selectable by software */
#define SCC_SOFTDETECT  0x0002  /* Option is detectable by software */
#define SCC_HARDSWITCH  0x0004  /* Option is a hardware switch (requires
                                   user-interaction */
#define SCC_EMULATE     0x0008  /* Option is emulated by driver */
#define SCC_CANDO       0x000f  /* driver supports option,if any of the
                                   above is set */

Here are some examples on how to use this options:

If you can select the dpi on your scanner via a hardware switch and the
driver is capable of reading its setting,you would specify:
SCC_SOFTDETECT|SCC_HARDSWITCH

If your scanner is fixed to one dpi-setting,there is no "HARDSWITCH" but the
driver will normally fake the fixed rate to be "detectable" (although no
real detection needs to be done,as the rate is fixed):
SCC_SOFTDETECT

In the case you can select a dpi setting via a switch but there is no way
for the driver to read this setting (this really shouldn't occur,but there
is really STRANGE hardware around) you should set SCC_HARDSWITCH.

This means for the application :
================================

If SCC_SOFTDETECT is not present,the user should be prompted for the value
of the parameter unless it is otherwise known (I really can't image a case,
where SCC_SOFTSELECT does not imply SCC_SOFTDETECT ...) and the value should
be explicitly set by a SMOD-call to tell the driver about it.

SCC_HARDSWITCH will mean that the application should prompt the user to set
up his hardware properly (except when it is known that this has already been
done e.g. when SOFTDETECT works ...)

The SCC_EMULATE option says that the driver will emulate this mode when
selected,even when the hardware is in another mode or does not support
this mode.(e.g. all monochrome scanners will normally emulate true-color-
mode by expanding the monochrome data to all the three RGB-Values).


The phys_*-fields contain the physical dimensions of the maximum
scan-window in mm.

The minmax-structs contain ranges for parameters,the struct is defined as
follows:

struct minmax {int min,max;};


The av_options-field contains the number of options available on this
particular scanner.This value is in the range of 0-32 (inclusive) and is
needed for the correct interpretation of the data from the HSIOCGOPT-call.

*********************************************************************
#define HSIOCGOPT               0x73e7  /* Get option descriptions */
*********************************************************************

This call will return a field of up to 32 option descriptors (it will
be enough to reserve av_options entrys) of the form

struct scanner_option {int  options;	/* Option availability */
                       char name[20];};

The 'options'-flag is treated like one of the above 'o_'-values - i.e. it
will tell you,if the option may be selected by Hardware or Software and if
it is soft-detectable or just some kind of emulated driver feature.

For options I would suggest a user-dialog showing the option-name to let the 
user select/deselect/view the options.

If this is not possible/desireable (e.g. for background-processes like OCR)
you should try to extract the meaning of an option from its name.

To ensure compatibility,device-driver-writers are encouraged to check their
ideas for naming some feature with me to avoid multiple names for the same
option and to enable me to update this paper.

Currently there is only one option used by a driver :

Option   : "Dithering"
Function : Turn on/off dithered greyscale-mode
Driver   : logi32.o
Author   : becka@hp.rz.uni-duesseldorf.de

**************************************************************
#define HSIOCGSCT               0x73e9  /* Get Scanner Type */
**************************************************************

This call will identify the scanner hardware,allowing the application to
take advantage of special features of a particular scanner that are not
accessible through the normal ioctl-interface.
It returns a structure :

struct scanner_type {
  char manufacturer[20],model[20];
};

**********************************************************
#define HSIOCGMOD               0x73ea  /* Get modeinfo */
**********************************************************

This call gets the current mode information of the scanner.

struct modeinfo_struct {
  int xdpi,ydpi;		/* resolution */
  int sc_mode;
  int depth;			/* number of different colors (-1) */
  int bpl;			/* bytes per scanline */
  int left,right;		/* margins in Pixels */
  int top,bottom;		/* margins in Lines */
  int bright;		        /* brightness */
  int contrast;		        /* contrast */
  int hue;		        /* hue */
  int sat;		        /* saturation */
  int options;			/* enabled options */
};

sc_mode can take one of the following values :

#define SCM_UNKNOWN 0           /* Scanner modes : */
#define SCM_MONO 1              /* 1 BitPerPixel   */
#define SCM_GREY 2              /* 8 BitsPerPixel  */
#define SCM_TRUE 3              /* 24 Bit RGB      */

In the case of 0,the scanner is in an undefined state (what should not
happen). You may try to set a new mode,but you should rather abort ...

The scan modes differ in the format of the transmitted data:

MONO-mode sends a bitstream of binary encoded black and white values,i.e.
reading 0x83 0x10 means that the pattern under the scanner head is
* . . . . . * *  . . . * . . . . ;
i.e. there are always 8 pixels per byte and a line always holds a multiple
of 8 pixels (this should be reflected through left and right,anyway ...).

GREY-mode sends a bytestream of greyvalues scaled up to the range 0-255.
The actual depth can be found by using the depth field,but even if depth
is 0 (i.e. the scanner is actually in a B&W mode), always sends 0 or 255
per pixel.I.e. there is one pixel ber byte.

TRUE-mode sends RGB-values as bytes.So there are 3 Bytes per pixel.
The actual resolution in depth should be filled with 0xrrggbb where
rr is the number of red colours the scanner can distinguish etc.
I.e. a 4096 color scanner (4bit red,green and blue) should report 0x0f0f0f
while a 24-bit model should report 0xffffff.

bpl holds the number of bytes per line that will be sent to the application
on a read call.

Left,right,top and bottom hold the set margins.

Bright,Contrast,Hue and Saturation hold the values for the respective
properties of the image.

Options is to be considered as a bit field of selected options.

**********************************************************
#define HSIOCSMOD               0x73eb  /* Set modeinfo */
**********************************************************

This call is used to set the scanner mode.Please note,that the structure
you provide is CHANGED to reflect the real values,the scanner or driver 
can handle.

E.g. to demand a 400dpi x/600dpi y-Scan in 24-bit mode at full depth and
with margins at 5-1003 (x),13-4000 (y) you would call SMOD with

{ 400,600,
  SCM_TRUE,
  0xffffff,
  0,/* bpl doesn't matter */
  5,1003,13,4000,
  ...
}

If the scanner can only support 300dpi on both axis,is set to SCM_MONO via 
a hardware switch (and the driver cannot convert the data [!]),supports only 
horizontal borders that are multiples of 8 and up to ten inch page length 
the structure will have changed to

{ 300,300,
  SCM_MONO,
  0,
  126,/* Bytes per line filled in */
  0,1008,13,3000
}

Please note,the the driver should be able to emulate TRUE-MODE,as some
lazy software might want to rely on it ...

*************************************************************************
#define HSIOCGREG               0x73ec  /* play with strange registers */
#define HSIOCSREG               0x73ef
*************************************************************************

This is for use in driver development and will normally not be accessible
to user-level applications.The functionality of this call may differ from
scanner to scanner or even driver to driver ...

*************************************************************************
#define HSIOCGBUF               0x73f0  /* get/set current buffer size */
#define HSIOCSBUF               0x73f1
*************************************************************************

Get/Set the current buffer size in scanlines.

*************************************************************************
#define HSIOCSSTH               0x73f2  /* get/set select(2) threshold */
#define HSIOCGSTH               0x73f3
*************************************************************************

Get/Set the select()-treshold.

*********************************************************************
#define HSIOCGSIB               0x73f4  /* get scanlines in buffer */
*********************************************************************

This may be used as some kind of fill-gauge for the internal buffers
of the scanner.This will be typically used by scanners with user-controlled
amount of data-flow (i.e. handscanners) to be able to signal the user to
scan slower,when buffers are getting full.

Bye, Andreas.

--
Scanner-driver developers that use this spec :

Andreas Beck		becka@hp.rz.uni-duesseldorf.de		(logi32)
Thomas Faehnle		Thomas.Faehnle@student.uni-ulm.de	(m105)
Michael Beck		beck@informatik.hu-berlin.de		(ac4096)
Germany

