sane-project-backends/backend/snapscan-options.c

1456 wiersze
55 KiB
C

/* sane - Scanner Access Now Easy.
Copyright (C) 1997, 1998, 2001 Franck Schnefra, Michel Roelofs,
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson,
Oliver Schwartz and Kevin Charter
This file is part of the SANE package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
This file is a component of the implementation of a backend for many
of the the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */
/* $Id$
SANE SnapScan backend */
/* init_options -- initialize the option set for a scanner; expects the
scanner structure's hardware configuration byte (hconfig) to be valid.
ARGS: a pointer to an existing scanner structure
RET: nothing
SIDE: the option set of *ps is initialized; this includes both
the option descriptors and the option values themselves */
static void init_options (SnapScan_Scanner * ps)
{
static SANE_Word resolutions_300[] =
{6, 50, 75, 100, 150, 200, 300};
static SANE_Word resolutions_600[] =
{8, 50, 75, 100, 150, 200, 300, 450, 600};
static SANE_Word resolutions_1200[] =
{10, 50, 75, 100, 150, 200, 300, 450, 600, 900, 1200};
static SANE_String_Const names_all[] =
{md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
static SANE_String_Const names_basic[] =
{md_colour, md_greyscale, md_lineart, NULL};
static SANE_String_Const preview_names_all[] =
{md_auto, md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
static SANE_String_Const preview_names_basic[] =
{md_auto, md_colour, md_greyscale, md_lineart, NULL};
SANE_Option_Descriptor *po = ps->options;
po[OPT_COUNT].name = SANE_NAME_NUM_OPTIONS;
po[OPT_COUNT].title = SANE_TITLE_NUM_OPTIONS;
po[OPT_COUNT].desc = SANE_DESC_NUM_OPTIONS;
po[OPT_COUNT].type = SANE_TYPE_INT;
po[OPT_COUNT].unit = SANE_UNIT_NONE;
po[OPT_COUNT].size = sizeof (SANE_Word);
po[OPT_COUNT].cap = SANE_CAP_SOFT_DETECT;
{
static SANE_Range count_range =
{NUM_OPTS, NUM_OPTS, 0};
po[OPT_COUNT].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_COUNT].constraint.range = &count_range;
}
po[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
po[OPT_MODE_GROUP].desc = "";
po[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
po[OPT_MODE_GROUP].cap = 0;
po[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_SCANRES].name = SANE_NAME_SCAN_RESOLUTION;
po[OPT_SCANRES].title = SANE_TITLE_SCAN_RESOLUTION;
po[OPT_SCANRES].desc = SANE_DESC_SCAN_RESOLUTION;
po[OPT_SCANRES].type = SANE_TYPE_INT;
po[OPT_SCANRES].unit = SANE_UNIT_DPI;
po[OPT_SCANRES].size = sizeof (SANE_Word);
po[OPT_SCANRES].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_SCANRES].constraint_type = SANE_CONSTRAINT_WORD_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S: /* WG changed */
po[OPT_SCANRES].constraint.word_list = resolutions_300;
break;
case SNAPSCANE50:
case SNAPSCANE52:
case PRISA5300:
case PRISA1240:
po[OPT_SCANRES].constraint.word_list = resolutions_1200;
break;
default:
po[OPT_SCANRES].constraint.word_list = resolutions_600;
break;
}
ps->res = DEFAULT_RES;
po[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
po[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
po[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
po[OPT_PREVIEW].type = SANE_TYPE_BOOL;
po[OPT_PREVIEW].unit = SANE_UNIT_NONE;
po[OPT_PREVIEW].size = sizeof (SANE_Word);
po[OPT_PREVIEW].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
ps->preview = DEFAULT_PREVIEW;
po[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
po[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
po[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
po[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
po[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
po[OPT_BRIGHTNESS].size = sizeof (int);
po[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRIGHTNESS].constraint.range = &brightness_range;
ps->bright = DEFAULT_BRIGHTNESS;
po[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
po[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
po[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
po[OPT_CONTRAST].type = SANE_TYPE_FIXED;
po[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
po[OPT_CONTRAST].size = sizeof (int);
po[OPT_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_CONTRAST].constraint.range = &contrast_range;
ps->contrast = DEFAULT_CONTRAST;
po[OPT_MODE].name = SANE_NAME_SCAN_MODE;
po[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
po[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
po[OPT_MODE].type = SANE_TYPE_STRING;
po[OPT_MODE].unit = SANE_UNIT_NONE;
po[OPT_MODE].size = 32;
po[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S:
po[OPT_MODE].constraint.string_list = names_basic;
break;
default:
po[OPT_MODE].constraint.string_list = names_all;
break;
}
ps->mode_s = md_colour;
ps->mode = MD_COLOUR;
po[OPT_PREVIEW_MODE].name = "preview-mode";
po[OPT_PREVIEW_MODE].title = SANE_I18N("Preview mode");
po[OPT_PREVIEW_MODE].desc = SANE_I18N(
"Select the mode for previews. Greyscale previews usually give "
"the best combination of speed and detail.");
po[OPT_PREVIEW_MODE].type = SANE_TYPE_STRING;
po[OPT_PREVIEW_MODE].unit = SANE_UNIT_NONE;
po[OPT_PREVIEW_MODE].size = 32;
po[OPT_PREVIEW_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
po[OPT_PREVIEW_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S:
po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_basic;
break;
default:
po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_all;
break;
}
ps->preview_mode_s = md_auto;
ps->preview_mode = ps->mode;
/* source */
po[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
po[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
po[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
po[OPT_SOURCE].type = SANE_TYPE_STRING;
po[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE;
po[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
{
static SANE_String_Const source_list[3];
int i = 0;
source_list[i++]= src_flatbed;
if (ps->hconfig & HCFG_TPO)
{
source_list[i++] = src_tpo;
po[OPT_SOURCE].cap ^= SANE_CAP_INACTIVE;
}
source_list[i] = 0;
po[OPT_SOURCE].size = max_string_size(source_list);
po[OPT_SOURCE].constraint.string_list = source_list;
ps->source = SRC_FLATBED;
ps->source_s = (SANE_Char *) strdup(source_list[0]);
}
po[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry");
po[OPT_GEOMETRY_GROUP].desc = "";
po[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
po[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
po[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_TLX].name = SANE_NAME_SCAN_TL_X;
po[OPT_TLX].title = SANE_TITLE_SCAN_TL_X;
po[OPT_TLX].desc = SANE_DESC_SCAN_TL_X;
po[OPT_TLX].type = SANE_TYPE_FIXED;
po[OPT_TLX].unit = SANE_UNIT_MM;
po[OPT_TLX].size = sizeof (SANE_Word);
po[OPT_TLX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_TLX].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_TLX].constraint.range = &(ps->pdev->x_range);
ps->tlx = ps->pdev->x_range.min;
po[OPT_TLY].name = SANE_NAME_SCAN_TL_Y;
po[OPT_TLY].title = SANE_TITLE_SCAN_TL_Y;
po[OPT_TLY].desc = SANE_DESC_SCAN_TL_Y;
po[OPT_TLY].type = SANE_TYPE_FIXED;
po[OPT_TLY].unit = SANE_UNIT_MM;
po[OPT_TLY].size = sizeof (SANE_Word);
po[OPT_TLY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_TLY].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_TLY].constraint.range = &(ps->pdev->y_range);
ps->tly = ps->pdev->y_range.min;
po[OPT_BRX].name = SANE_NAME_SCAN_BR_X;
po[OPT_BRX].title = SANE_TITLE_SCAN_BR_X;
po[OPT_BRX].desc = SANE_DESC_SCAN_BR_X;
po[OPT_BRX].type = SANE_TYPE_FIXED;
po[OPT_BRX].unit = SANE_UNIT_MM;
po[OPT_BRX].size = sizeof (SANE_Word);
po[OPT_BRX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_BRX].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRX].constraint.range = &(ps->pdev->x_range);
ps->brx = ps->pdev->x_range.max;
po[OPT_BRY].name = SANE_NAME_SCAN_BR_Y;
po[OPT_BRY].title = SANE_TITLE_SCAN_BR_Y;
po[OPT_BRY].desc = SANE_DESC_SCAN_BR_Y;
po[OPT_BRY].type = SANE_TYPE_FIXED;
po[OPT_BRY].unit = SANE_UNIT_MM;
po[OPT_BRY].size = sizeof (SANE_Word);
po[OPT_BRY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_BRY].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRY].constraint.range = &(ps->pdev->y_range);
ps->bry = ps->pdev->y_range.max;
po[OPT_PREDEF_WINDOW].name = "predef-window";
po[OPT_PREDEF_WINDOW].title = SANE_I18N("Predefined settings");
po[OPT_PREDEF_WINDOW].desc = SANE_I18N(
"Provides standard scanning areas for photographs, printed pages "
"and the like.");
po[OPT_PREDEF_WINDOW].type = SANE_TYPE_STRING;
po[OPT_PREDEF_WINDOW].unit = SANE_UNIT_NONE;
po[OPT_PREDEF_WINDOW].size = 32;
po[OPT_PREDEF_WINDOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
{
static SANE_String_Const names[] =
{pdw_none, pdw_6X4, pdw_8X10, pdw_85X11, NULL};
po[OPT_PREDEF_WINDOW].constraint_type = SANE_CONSTRAINT_STRING_LIST;
po[OPT_PREDEF_WINDOW].constraint.string_list = names;
}
ps->predef_window = pdw_none;
po[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement");
po[OPT_ENHANCEMENT_GROUP].desc = "";
po[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
po[OPT_ENHANCEMENT_GROUP].cap = 0;
po[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL;
po[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL;
po[OPT_QUALITY_CAL].desc = SANE_DESC_QUALITY_CAL;
po[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL;
po[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE;
po[OPT_QUALITY_CAL].size = sizeof (SANE_Bool);
po[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_QUALITY_CAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
ps->val[OPT_QUALITY_CAL].b = DEFAULT_QUALITY;
/* Disable quality calibration option if not supported
Note: Snapscan e52 does not support quality calibration,
although HCFG_CAL_ALLOWED is set. */
if ((!(ps->hconfig & HCFG_CAL_ALLOWED))
|| (ps->pdev->model == SNAPSCANE52)) {
po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE;
ps->val[OPT_QUALITY_CAL].b = SANE_FALSE;
}
po[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL;
po[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_BIND].size = sizeof (SANE_Bool);
po[OPT_GAMMA_BIND].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE;
ps->val[OPT_GAMMA_BIND].b = DEFAULT_GAMMA_BIND;
po[OPT_GAMMA_GS].name = SANE_NAME_ANALOG_GAMMA;
po[OPT_GAMMA_GS].title = SANE_TITLE_ANALOG_GAMMA;
po[OPT_GAMMA_GS].desc = SANE_DESC_ANALOG_GAMMA;
po[OPT_GAMMA_GS].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_GS].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_GS].size = sizeof (SANE_Word);
po[OPT_GAMMA_GS].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_GAMMA_GS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_GS].constraint.range = &gamma_range;
ps->gamma_gs = DEFAULT_GAMMA;
po[OPT_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_R].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_R].size = sizeof (SANE_Word);
po[OPT_GAMMA_R].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_R].constraint.range = &gamma_range;
ps->gamma_r = DEFAULT_GAMMA;
po[OPT_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_G].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_G].size = sizeof (SANE_Word);
po[OPT_GAMMA_G].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_G].constraint.range = &gamma_range;
ps->gamma_g = DEFAULT_GAMMA;
po[OPT_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_B].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_B].size = sizeof (SANE_Word);
po[OPT_GAMMA_B].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_B].constraint.range = &gamma_range;
ps->gamma_b = DEFAULT_GAMMA;
po[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
po[OPT_CUSTOM_GAMMA].unit = SANE_UNIT_NONE;
po[OPT_CUSTOM_GAMMA].size = sizeof (SANE_Bool);
po[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
ps->val[OPT_CUSTOM_GAMMA].b = DEFAULT_CUSTOM_GAMMA;
po[OPT_GAMMA_VECTOR_GS].name = SANE_NAME_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].title = SANE_TITLE_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].desc = SANE_DESC_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_GS].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_GS].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_GS].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_GS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_GS].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_GS].wa = ps->gamma_table_gs;
po[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_R].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_R].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_R].wa = ps->gamma_table_r;
po[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_G].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_G].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_G].wa = ps->gamma_table_g;
po[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_B].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_B].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_B].wa = ps->gamma_table_b;
po[OPT_HALFTONE].name = SANE_NAME_HALFTONE;
po[OPT_HALFTONE].title = SANE_TITLE_HALFTONE;
po[OPT_HALFTONE].desc = SANE_DESC_HALFTONE;
po[OPT_HALFTONE].type = SANE_TYPE_BOOL;
po[OPT_HALFTONE].unit = SANE_UNIT_NONE;
po[OPT_HALFTONE].size = sizeof (SANE_Bool);
po[OPT_HALFTONE].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_NONE;
ps->halftone = DEFAULT_HALFTONE;
po[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
po[OPT_HALFTONE_PATTERN].unit = SANE_UNIT_NONE;
po[OPT_HALFTONE_PATTERN].size = 32;
po[OPT_HALFTONE_PATTERN].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->hconfig & HCFG_HT)
{
case HCFG_HT:
/* both 16x16, 8x8 matrices */
{
static SANE_String_Const names[] = {dm_dd8x8, dm_dd16x16, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd8x8;
}
break;
case HCFG_HT16:
/* 16x16 matrices only */
{
static SANE_String_Const names[] = {dm_dd16x16, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd16x16;
}
break;
case HCFG_HT8:
/* 8x8 matrices only */
{
static SANE_String_Const names[] = {dm_dd8x8, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd8x8;
}
break;
default:
/* no halftone matrices */
{
static SANE_String_Const names[] = {dm_none, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_none;
}
}
po[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
po[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
po[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
po[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
po[OPT_NEGATIVE].unit = SANE_UNIT_NONE;
po[OPT_NEGATIVE].size = sizeof (SANE_Bool);
po[OPT_NEGATIVE].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
ps->negative = DEFAULT_NEGATIVE;
po[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
po[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
po[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
po[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
po[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
po[OPT_THRESHOLD].size = sizeof (SANE_Int);
po[OPT_THRESHOLD].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_THRESHOLD].constraint.range = &positive_percent_range;
ps->threshold = DEFAULT_THRESHOLD;
po[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced");
po[OPT_ADVANCED_GROUP].desc = "";
po[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
po[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
po[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_RGB_LPR].name = "rgb-lpr";
po[OPT_RGB_LPR].title = SANE_I18N("Colour lines per read");
po[OPT_RGB_LPR].desc = lpr_desc;
po[OPT_RGB_LPR].type = SANE_TYPE_INT;
po[OPT_RGB_LPR].unit = SANE_UNIT_NONE;
po[OPT_RGB_LPR].size = sizeof (SANE_Word);
po[OPT_RGB_LPR].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
po[OPT_RGB_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_RGB_LPR].constraint.range = &lpr_range;
ps->rgb_lpr = def_rgb_lpr;
po[OPT_GS_LPR].name = "gs-lpr";
po[OPT_GS_LPR].title = SANE_I18N("Greyscale lines per read");
po[OPT_GS_LPR].desc = lpr_desc;
po[OPT_GS_LPR].type = SANE_TYPE_INT;
po[OPT_GS_LPR].unit = SANE_UNIT_NONE;
po[OPT_GS_LPR].size = sizeof (SANE_Word);
po[OPT_GS_LPR].cap = SANE_CAP_SOFT_SELECT
| SANE_CAP_SOFT_DETECT
| SANE_CAP_ADVANCED
| SANE_CAP_INACTIVE;
po[OPT_GS_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GS_LPR].constraint.range = &lpr_range;
ps->gs_lpr = def_gs_lpr;
po[OPT_SCSI_CMDS].title = SANE_I18N("SCSI commands (for debugging)");
po[OPT_SCSI_CMDS].desc = "";
po[OPT_SCSI_CMDS].type = SANE_TYPE_GROUP;
po[OPT_SCSI_CMDS].cap = SANE_CAP_ADVANCED;
po[OPT_INQUIRY].name = "do-inquiry";
po[OPT_INQUIRY].title = SANE_I18N("Inquiry");
po[OPT_INQUIRY].desc = SANE_I18N(
"Send an Inquiry command to the scanner and dump out some of "
"the current settings.");
po[OPT_INQUIRY].type = SANE_TYPE_BUTTON;
po[OPT_INQUIRY].cap = SANE_CAP_ADVANCED;
po[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_SELF_TEST].name = "do-self-test";
po[OPT_SELF_TEST].title = SANE_I18N("Self test");
po[OPT_SELF_TEST].desc = SANE_I18N(
"Send a Self Test command to the scanner and report the result.");
po[OPT_SELF_TEST].type = SANE_TYPE_BUTTON;
po[OPT_SELF_TEST].cap = SANE_CAP_ADVANCED;
po[OPT_SELF_TEST].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_REQ_SENSE].name = "do-req-sense";
po[OPT_REQ_SENSE].title = SANE_I18N("Request sense");
po[OPT_REQ_SENSE].desc = SANE_I18N(
"Send a Request Sense command to the scanner, and print out the sense "
"report.");
po[OPT_REQ_SENSE].type = SANE_TYPE_BUTTON;
po[OPT_REQ_SENSE].cap = SANE_CAP_ADVANCED;
po[OPT_REQ_SENSE].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_REL_UNIT].name = "do-rel-unit";
po[OPT_REL_UNIT].title = SANE_I18N("Release unit (cancel)");
po[OPT_REL_UNIT].desc = SANE_I18N(
"Send a Release Unit command to the scanner. This is the same as "
"a cancel command.");
po[OPT_REL_UNIT].type = SANE_TYPE_BUTTON;
po[OPT_REL_UNIT].cap = SANE_CAP_ADVANCED;
po[OPT_REL_UNIT].constraint_type = SANE_CONSTRAINT_NONE;
}
const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h,
SANE_Int n)
{
DBG (DL_CALL_TRACE,
"sane_snapscan_get_option_descriptor (%p, %ld)\n",
(void *) h,
(long) n);
if ((n >= 0) && (n < NUM_OPTS))
return ((SnapScan_Scanner *) h)->options + n;
return NULL;
}
/* Activates or deactivates options depending on mode */
static void control_options(SnapScan_Scanner *pss)
{
/* first deactivate all options */
pss->options[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_GS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_GS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
if ((pss->mode == MD_COLOUR) ||
((pss->mode == MD_BILEVELCOLOUR) && (pss->hconfig & HCFG_HT) &&
pss->halftone))
{
pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_CUSTOM_GAMMA].b)
{
if (pss->val[OPT_GAMMA_BIND].b)
{
pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
}
}
else
{
pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_GAMMA_BIND].b)
{
pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_GAMMA_R].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_G].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_B].cap &= ~SANE_CAP_INACTIVE;
}
}
}
else if ((pss->mode == MD_GREYSCALE) ||
((pss->mode == MD_LINEART) && (pss->hconfig & HCFG_HT) &&
pss->halftone))
{
pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_CUSTOM_GAMMA].b)
{
pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
}
}
}
SANE_Status sane_control_option (SANE_Handle h,
SANE_Int n,
SANE_Action a,
void *v,
SANE_Int *i)
{
static const char *me = "sane_snapscan_control_option";
SnapScan_Scanner *pss = h;
SnapScan_Device *pdev = pss->pdev;
static SANE_Status status;
DBG (DL_CALL_TRACE,
"%s (%p, %ld, %ld, %p, %p)\n",
me,
(void *) h,
(long) n,
(long) a,
v,
(void *) i);
status = open_scanner (pss);
CHECK_STATUS (status, me, "open_scanner");
/* possible authorization required */
switch (a)
{
case SANE_ACTION_GET_VALUE:
/* prevent getting of inactive options */
if (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap)) {
return SANE_STATUS_INVAL;
}
switch (n)
{
case OPT_COUNT:
*(SANE_Int *) v = NUM_OPTS;
break;
case OPT_SCANRES:
*(SANE_Int *) v = pss->res;
break;
case OPT_PREVIEW:
*(SANE_Bool *) v = pss->preview;
break;
case OPT_MODE:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->mode_s,
(SANE_String) v);
strcpy ((SANE_String) v, pss->mode_s);
break;
case OPT_PREVIEW_MODE:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->preview_mode_s,
(SANE_String) v);
strcpy ((SANE_String) v, pss->preview_mode_s);
break;
case OPT_SOURCE:
strcpy (v, pss->source_s);
break;
case OPT_TLX:
*(SANE_Fixed *) v = pss->tlx;
break;
case OPT_TLY:
*(SANE_Fixed *) v = pss->tly;
break;
case OPT_BRX:
*(SANE_Fixed *) v = pss->brx;
break;
case OPT_BRY:
*(SANE_Fixed *) v = pss->bry;
break;
case OPT_BRIGHTNESS:
*(SANE_Int *) v = pss->bright << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_CONTRAST:
*(SANE_Int *) v = pss->contrast << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_PREDEF_WINDOW:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->predef_window,
(SANE_String) v);
strcpy ((SANE_String) v, pss->predef_window);
break;
case OPT_GAMMA_GS:
*(SANE_Fixed *) v = pss->gamma_gs;
break;
case OPT_GAMMA_R:
*(SANE_Fixed *) v = pss->gamma_r;
break;
case OPT_GAMMA_G:
*(SANE_Fixed *) v = pss->gamma_g;
break;
case OPT_GAMMA_B:
*(SANE_Fixed *) v = pss->gamma_b;
break;
case OPT_CUSTOM_GAMMA:
case OPT_GAMMA_BIND:
case OPT_QUALITY_CAL:
*(SANE_Bool *) v = pss->val[n].b;
break;
case OPT_GAMMA_VECTOR_GS:
case OPT_GAMMA_VECTOR_R:
case OPT_GAMMA_VECTOR_G:
case OPT_GAMMA_VECTOR_B:
memcpy (v, pss->val[n].wa, pss->options[n].size);
break;
case OPT_HALFTONE:
*(SANE_Bool *) v = pss->halftone;
break;
case OPT_HALFTONE_PATTERN:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->dither_matrix,
(SANE_String) v);
strcpy ((SANE_String) v, pss->dither_matrix);
break;
case OPT_NEGATIVE:
*(SANE_Bool *) v = pss->negative;
break;
case OPT_THRESHOLD:
*(SANE_Int *) v = pss->threshold << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_RGB_LPR:
*(SANE_Int *) v = pss->rgb_lpr;
break;
case OPT_GS_LPR:
*(SANE_Int *) v = pss->gs_lpr;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
break;
case SANE_ACTION_SET_VALUE:
if (i)
*i = 0;
/* prevent setting of inactive options */
if ((!SANE_OPTION_IS_SETTABLE(pss->options[n].cap)) ||
(!SANE_OPTION_IS_ACTIVE(pss->options[n].cap))) {
return SANE_STATUS_INVAL;
}
status = sanei_constrain_value(&pss->options[n], v, i);
if (status != SANE_STATUS_GOOD) {
return status;
}
switch (n)
{
case OPT_COUNT:
return SANE_STATUS_UNSUPPORTED;
case OPT_SCANRES:
pss->res = *(SANE_Int *) v;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_PREVIEW:
pss->preview = *(SANE_Bool *) v;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_MODE:
{
char *s = (SANE_String) v;
if (strcmp (s, md_colour) == 0)
{
pss->mode_s = md_colour;
pss->mode = MD_COLOUR;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_COLOUR;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_bilevelcolour) == 0)
{
int ht_cap = pss->hconfig & HCFG_HT;
pss->mode_s = md_bilevelcolour;
pss->mode = MD_BILEVELCOLOUR;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_BILEVELCOLOUR;
if (ht_cap)
pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
if (ht_cap && pss->halftone)
{
pss->options[OPT_HALFTONE_PATTERN].cap &=
~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |=
SANE_CAP_INACTIVE;
}
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_greyscale) == 0)
{
pss->mode_s = md_greyscale;
pss->mode = MD_GREYSCALE;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_GREYSCALE;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_lineart) == 0)
{
int ht_cap = pss->hconfig & HCFG_HT;
pss->mode_s = md_lineart;
pss->mode = MD_LINEART;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_LINEART;
if (ht_cap)
pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
if (ht_cap && pss->halftone)
{
pss->options[OPT_HALFTONE_PATTERN].cap &=
~SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |=
SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
}
pss->options[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal mode "
"string \"%s\"\n",
me,
s);
}
}
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_PREVIEW_MODE:
{
char *s = (SANE_String) v;
if (strcmp (s, md_auto) == 0)
{
pss->preview_mode_s = md_auto;
pss->preview_mode = pss->mode;
}
else if (strcmp (s, md_colour) == 0)
{
pss->preview_mode_s = md_colour;
pss->preview_mode = MD_COLOUR;
}
else if (strcmp (s, md_bilevelcolour) == 0)
{
pss->preview_mode_s = md_bilevelcolour;
pss->preview_mode = MD_BILEVELCOLOUR;
}
else if (strcmp (s, md_greyscale) == 0)
{
pss->preview_mode_s = md_greyscale;
pss->preview_mode = MD_GREYSCALE;
}
else if (strcmp (s, md_lineart) == 0)
{
pss->preview_mode_s = md_lineart;
pss->preview_mode = MD_LINEART;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal mode string "
"\"%s\"\n",
me,
s);
}
if (i)
*i = 0;
break;
}
case OPT_SOURCE:
if (strcmp(v, src_flatbed) == 0)
{
pss->source = SRC_FLATBED;
pss->pdev->x_range.max = x_range_fb.max;
pss->pdev->y_range.max = y_range_fb.max;
}
else if (strcmp(v, src_tpo) == 0)
{
pss->source = SRC_TPO;
pss->pdev->x_range.max = x_range_tpo.max;
pss->pdev->y_range.max = y_range_tpo.max;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal source string "
"\"%s\"\n",
me,
(char *) v);
}
/* Adjust actual range values to new max values */
if (pss->brx > pss->pdev->x_range.max)
pss->brx = pss->pdev->x_range.max - pdev->x_range.quant;
if (pss->bry > pss->pdev->y_range.max)
pss->bry = pss->pdev->y_range.max - pdev->y_range.quant;
pss->predef_window = pdw_none;
if (pss->source_s)
free (pss->source_s);
pss->source_s = (SANE_Char *) strdup(v);
if (i)
*i = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_TLX:
pss->tlx = *(SANE_Fixed *) v;
pss->predef_window = pdw_none;
if (fabs(pss->tlx - pdev->x_range.max) < pdev->x_range.quant) {
pss->tlx -= pdev->x_range.quant;
}
if (pss->brx < pss->tlx) {
pss->brx = pss->tlx + pdev->x_range.quant;
}
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_TLY:
pss->tly = *(SANE_Fixed *) v;
if (fabs(pss->tly - pdev->y_range.max) < pdev->y_range.quant) {
pss->tly -= pdev->y_range.quant;
}
pss->predef_window = pdw_none;
if (pss->bry < pss->tly) {
pss->bry = pss->tly + pdev->y_range.quant;
}
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRX:
pss->brx = *(SANE_Fixed *) v;
if (fabs(pss->brx - pdev->x_range.min) < pdev->x_range.quant) {
pss->brx += pdev->x_range.quant;
}
if (pss->brx < pss->tlx) {
pss->tlx = pss->brx - pdev->x_range.quant;
}
pss->predef_window = pdw_none;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRY:
pss->bry = *(SANE_Fixed *) v;
if (fabs(pss->bry - pdev->y_range.min) < pdev->y_range.quant) {
pss->bry += pdev->y_range.quant;
}
if (pss->bry < pss->tly) {
pss->tly = pss->bry - pdev->y_range.quant;
}
pss->predef_window = pdw_none;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRIGHTNESS:
pss->bright = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
if (i)
*i = 0;
break;
case OPT_CONTRAST:
pss->contrast = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
if (i)
*i = 0;
break;
case OPT_PREDEF_WINDOW:
{
char *s = (SANE_String) v;
if (strcmp (s, pdw_none) != 0)
{
pss->tlx = 0;
pss->tly = 0;
if (strcmp (s, pdw_6X4) == 0)
{
pss->predef_window = pdw_6X4;
pss->brx = SANE_FIX (6.0*MM_PER_IN);
pss->bry = SANE_FIX (4.0*MM_PER_IN);
}
else if (strcmp (s, pdw_8X10) == 0)
{
pss->predef_window = pdw_8X10;
pss->brx = SANE_FIX (8.0*MM_PER_IN);
pss->bry = SANE_FIX (10.0*MM_PER_IN);
}
else if (strcmp (s, pdw_85X11) == 0)
{
pss->predef_window = pdw_85X11;
pss->brx = SANE_FIX (8.5*MM_PER_IN);
pss->bry = SANE_FIX (11.0*MM_PER_IN);
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: trying to set predef window with "
"garbage value.", me);
pss->predef_window = pdw_none;
pss->brx = SANE_FIX (6.0*MM_PER_IN);
pss->bry = SANE_FIX (4.0*MM_PER_IN);
}
}
else
{
pss->predef_window = pdw_none;
}
}
if (i)
*i = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_GAMMA_GS:
pss->gamma_gs = *(SANE_Fixed *) v;
if (i)
*i = 0;
break;
case OPT_GAMMA_R:
pss->gamma_r = *(SANE_Fixed *) v;
if (i)
*i = 0;
break;
case OPT_GAMMA_G:
pss->gamma_g = *(SANE_Fixed *) v;
if (i)
*i = 0;
break;
case OPT_GAMMA_B:
pss->gamma_b = *(SANE_Fixed *) v;
if (i)
*i = 0;
break;
case OPT_QUALITY_CAL:
pss->val[n].b = *(SANE_Bool *)v;
if (i)
*i = 0;
break;
case OPT_CUSTOM_GAMMA:
case OPT_GAMMA_BIND:
{
SANE_Bool b = *(SANE_Bool *) v;
if (b == pss->val[n].b) { break; }
pss->val[n].b = b;
control_options (pss);
if (i)
{
*i |= SANE_INFO_RELOAD_OPTIONS;
}
break;
}
case OPT_GAMMA_VECTOR_GS:
case OPT_GAMMA_VECTOR_R:
case OPT_GAMMA_VECTOR_G:
case OPT_GAMMA_VECTOR_B:
memcpy(pss->val[n].wa, v, pss->options[n].size);
if (i)
*i = 0;
break;
case OPT_HALFTONE:
pss->halftone = *(SANE_Bool *) v;
if (pss->halftone)
{
switch (pss->mode)
{
case MD_BILEVELCOLOUR:
break;
case MD_LINEART:
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
break;
default:
break;
}
pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
if (pss->mode == MD_LINEART)
pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
}
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_HALFTONE_PATTERN:
{
char *s = (SANE_String) v;
if (strcmp (s, dm_dd8x8) == 0)
{
pss->dither_matrix = dm_dd8x8;
}
else if (strcmp (s, dm_dd16x16) == 0)
{
pss->dither_matrix = dm_dd16x16;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal halftone pattern "
"string \"%s\"\n",
me,
s);
}
}
if (i)
*i = 0;
break;
case OPT_NEGATIVE:
pss->negative = *(SANE_Bool *) v;
if (i)
*i = 0;
break;
case OPT_THRESHOLD:
pss->threshold = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
if (i)
*i = 0;
break;
case OPT_INQUIRY:
status = inquiry (pss);
CHECK_STATUS (status, me, "inquiry");
DBG (0,
"\nInquiry results:\n"
"\tScanner: %s\n"
"\thardware config: 0x%x\n"
"\tA/D converter: %s\n"
"\tAuto-document feeder: %s\n"
"\tTransparency option: %s\n"
"\tRing buffer: %s\n"
"\t16x16 halftone matrix support: %s\n"
"\t8x8 halftone matrix support: %s\n"
"\tCalibration allowed: %s\n"
"\toptical resolution: %lu\n"
"\tscan resolution: %lu\n"
"\tnumber of lines: %lu\n"
"\tbytes per line: %lu\n"
"\tpixels per line: %lu\n"
"\tms per line: %f\n"
"\texposure time: %c.%c ms\n"
"\tred offset: %ld\n"
"\tgreen offset: %ld\n"
"\tblue offset: %ld\n"
"\tfirmware: %s\n\n",
pss->buf + INQUIRY_VENDOR,
pss->hconfig,
(pss->hconfig & HCFG_ADC) ? "10-bit" : "8-bit",
(pss->hconfig & HCFG_ADF) ? "Yes" : "No",
(pss->hconfig & HCFG_TPO) ? "Yes" : "No",
(pss->hconfig & HCFG_RB) ? "Yes" : "No",
(pss->hconfig & HCFG_HT16) ? "Yes" : "No",
(pss->hconfig & HCFG_HT8) ? "Yes" : "No",
(pss->hconfig & HCFG_CAL_ALLOWED) ? "Yes" : "No",
(u_long) pss->actual_res,
(u_long) pss->res,
(u_long) pss->lines,
(u_long) pss->bytes_per_line,
(u_long) pss->pixels_per_line,
(double) pss->ms_per_line,
pss->buf[INQUIRY_EXPTIME1] + '0',
pss->buf[INQUIRY_EXPTIME2] + '0',
(long) pss->chroma_offset[R_CHAN],
(long) pss->chroma_offset[G_CHAN],
(long) pss->chroma_offset[B_CHAN],
pss->buf + INQUIRY_FIRMWARE);
break;
case OPT_SELF_TEST:
status = send_diagnostic (pss);
if (status == SANE_STATUS_GOOD)
DBG (0, "Passes self-test.\n");
CHECK_STATUS (status, me, "self_test");
break;
case OPT_REQ_SENSE:
status = request_sense (pss);
CHECK_STATUS (status, me, "request_sense");
if (pss->sense_str)
DBG (0, "Scanner sense: %s\n", pss->sense_str);
if (pss->as_str)
DBG (0, "Scanner ASC/ASCQ: %s\n", pss->as_str);
break;
case OPT_REL_UNIT:
release_unit (pss);
DBG (0, "Release unit sent.\n");
break;
case OPT_RGB_LPR:
pss->rgb_lpr = *(SANE_Int *) v;
if (i)
*i = 0;
break;
case OPT_GS_LPR:
pss->gs_lpr = *(SANE_Int *) v;
if (i)
*i = 0;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
DBG (DL_VERBOSE, "%s: option %s set to value ",
me, pss->options[n].name);
switch (pss->options[n].type)
{
case SANE_TYPE_INT:
DBG (DL_VERBOSE, "%ld\n", (long) (*(SANE_Int *) v));
break;
case SANE_TYPE_BOOL:
{
char *valstr = (*(SANE_Bool *) v == SANE_TRUE) ? "TRUE" : "FALSE";
DBG (DL_VERBOSE, "%s\n", valstr);
}
break;
default:
DBG (DL_VERBOSE, "other than an integer or boolean.\n");
break;
}
break;
case SANE_ACTION_SET_AUTO:
switch (n)
{
case OPT_COUNT:
break;
case OPT_SCANRES:
pss->res = 300;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_PREVIEW:
pss->preview = SANE_FALSE;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_MODE:
pss->mode_s = md_colour;
pss->mode = MD_COLOUR;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_PREVIEW_MODE:
pss->preview_mode_s = md_greyscale;
pss->preview_mode = MD_GREYSCALE;
if (i)
*i = 0;
break;
case OPT_TLX:
pss->tlx = pss->pdev->x_range.min;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_TLY:
pss->tly = pss->pdev->y_range.min;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRX:
pss->brx = pss->pdev->x_range.max;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRY:
pss->bry = pss->pdev->y_range.max;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_PREDEF_WINDOW:
pss->predef_window = pdw_none;
if (i)
*i = SANE_INFO_RELOAD_PARAMS;
break;
case OPT_GAMMA_GS:
pss->gamma_gs = DEFAULT_GAMMA;
if (i)
*i = 0;
break;
case OPT_GAMMA_R:
pss->gamma_r = DEFAULT_GAMMA;
if (i)
*i = 0;
break;
case OPT_GAMMA_G:
pss->gamma_g = DEFAULT_GAMMA;
if (i)
*i = 0;
break;
case OPT_GAMMA_B:
pss->gamma_b = DEFAULT_GAMMA;
if (i)
*i = 0;
break;
case OPT_HALFTONE:
pss->halftone = DEFAULT_HALFTONE;
if (pss->halftone)
{
pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
}
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_HALFTONE_PATTERN:
pss->dither_matrix = dm_dd8x8;
if (i)
*i = 0;
break;
case OPT_NEGATIVE:
pss->negative = DEFAULT_NEGATIVE;
if (i)
*i = 0;
break;
case OPT_THRESHOLD:
pss->threshold = DEFAULT_THRESHOLD;
if (i)
*i = 0;
break;
case OPT_RGB_LPR:
pss->rgb_lpr = def_rgb_lpr;
if (i)
*i = 0;
break;
case OPT_GS_LPR:
pss->gs_lpr = def_gs_lpr;
if (i)
*i = 0;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
break;
default:
DBG (DL_MAJOR_ERROR, "%s: invalid action code %ld\n", me, (long) a);
return SANE_STATUS_UNSUPPORTED;
}
close_scanner (pss);
return SANE_STATUS_GOOD;
}
/*
* $Log$
* Revision 1.1 2002/03/24 12:32:26 oliverschwartz
* Snapscan backend version 1.4.9
*
* Revision 1.1 2002/03/24 12:07:15 oliverschwartz
* Moved option functions from snapscan.c to snapscan-options.c
*
*
* */