[sane-devel] SANE V2

Enno Fennema e.fennema@dataweb.nl
Wed, 04 Dec 2002 11:08:31 +0100

I would like to make some comments on the SANE 2.06 draft standard.

They represent my personal preferences and proposals and are offerered
for discussion but rather than prefixing each statement with 'I
think...' 'I propose...' etc. 
They are presented as statements of fact, which they are not.
Some rationale or comment is included within << and >>

One preliminary question: Who does turn the switch when and decide to go
to version 2.0 ?

2) SANE_Handle
A SANE_Handle points to a very important structure, viz.

typedef struct SANE_HANDLE {
    SANE_Device	*device;
    SANE_Status	(*init) (SANE_Int * version_code, SANE_Auth_Callback
    void	(*exit) (void);
    SANE_Status (*get_devices) (SANE_Device **device_list, SANE_Bool
    SANE_Status (*open) (SANE_String_Const devicename);
    void	(*close)(void);
    const SANE_Option_Descriptor* (*sane_get_option_descriptor)(SANE_Int
    SANE_Status (*control_option) (SANE_Int option, SANE_Action action,
void *value, SANE_Int * info);
    SANE_Status (*get_parameters)(SANE_Parameters * params);
    SANE_Status (*start) (void);
    SANE_Status (*read) (SANE_Byte * data, SANE_Int max_length, SANE_Int
* length);
    void 	(*cancel) (void);
    SANE_Status (*set_io_mode) (SANE_Bool non_blocking);
    SANE_Status (*get_select_fd) (SANE_Int * fd);


All function calls can then take the the form
and the handle need no longer be given as the first parameter.

This also obviates the fiddling of backend related names and looking
them up after dynamically loading a backend. 
Now only lookup the backend name, which returns the address of the
handle through which all backend functions can be accessed.

Usually a backend deals with one single device or a few strongly related
devices, eg. different models of scanners from one manufacturer.
For a meta-backend the definition of 'related' can be quite wide, in the
extreme case 'all devices for which specific backends are available on
this system'.

The sane_open() function creates a nexus between a frontend and a
device. The backend dealing with device must note and maintain that
nexus until sane_close().

Each backend has exactly one struct SANE_HANDLE with the backend name as
name. This allows the frontend or meta backend to know how to get the
address of the handle of a backend with dlsym().

If a device has been open()ed h->device points to that SANE_Device, 
otherwise h->device == NULL.
The backend either through the device pointer or by other internal means
must know whether a device model is currently open and what model it is.

The handle is the sole link between a frontend and the currently
selected backend.
whether meta- or physical.

2) SANE_Device

typedef struct SANE_Device {
    struct SANE_Device *next;
    SANE_String_Const name;	/* unique device name */
    SANE_String_Const vendor;	/* device vendor string */
    SANE_String_Const model;	/* device model name */
    SANE_String_Const type;	/* device type (e.g., "flatbed scanner") */
    SANE_String       devname;	/* from sane.conf eg. /dev/usbscanner0 */ 
}	SANE_Device;

next pointer: If sane_get_devices() returns a list of devices rather
than an array it is easier for a meta-backend to string all those lists

When enquiring into models managed by a particular backend
sane_get_devices need only return the pointer to the first device
managed by it, assuming that in the backend they are also linked into a

devname: How to open the device with an operating system dependent way.
See also comments on config file.

I have no serious problems with all the other fields proposed already
but am worried that you may be going overboard with detail  like which
floor the printer is on and e-mail addresses.

Most people use only very few scanners and they know which one is which.

4) sanei
Probably stands for SANE Internal ???.
The available functions, even though their use appears to be optional,
deserve some documentation.

In my view sane_strstatus() is a sanei_ rather than a sane_ function.

5) Option descriptor
Include a one-character shortname for common options to be used by eg.

Is there any point in including a SANE_Value (union word, fixed, char*)
in an option descriptor
containing the current value? Not quite sure myself/not very important.

6) Configuration files
Agree a format for a standard /etc/sane.conf file. 
Could by commandline option use other path, etc.

Backends need at least a method to derive the name of the device as used
by the operating system but could benefit from some configuration
information, calibration settings etc.

My preferred format is somewhat like Windows ini files.

The file consists of a number sections consisting of a number of lines. 

A '#' symbol, not within quotes,  and everything on a line beyond it is
ignored, as are totally blank lines.

A section start with a line containing only the section name in square
brackets and ends at the next section or at end of file.

Each line consists of a number of words. 
Words are essentially characters separated by white space.
White space is a space, a tab, a newline or carriage return.
Characters, including whitespace, enclosed in double quotes are treated
as one word.

The first word on each line is the type of configuration data. Standard
lines could be:

    scanner <name> <backend> <opsysname>

eg. scanner "Canon N656U" canonusb /dev/usbscanner0


    alias myscanner "Canon N656U"

A backend (and a frontend if it so wishes) may read all sections and
ignore those it does not need/understand.
The only obligatory section is [Backends] followed by one line for each
available backend.

Each backend can decide on its own configuration data within its own
sections always named
[be-name model-name]
A configuration file would look something like:

    def myscanner canonusb N656U

    model Canoscan N656U

    [Canoscan N656U]
    vendor 0x02A9
    product 0x2206
    sysname /dev/usbscanner0
    saturationRed 2.44
    saturationGreen 1.37
    saturationBlue 1.08

Would appreciate comments on the points raised.

Enno Fennema