diff options
Diffstat (limited to 'backend/snapscan-options.c')
-rw-r--r-- | backend/snapscan-options.c | 1922 |
1 files changed, 1922 insertions, 0 deletions
diff --git a/backend/snapscan-options.c b/backend/snapscan-options.c new file mode 100644 index 0000000..15f3a4a --- /dev/null +++ b/backend/snapscan-options.c @@ -0,0 +1,1922 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 1997, 1998, 2001, 2013 Franck Schnefra, Michel Roelofs, + Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, + Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson, + Andrew Goodbody, 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 */ + +/* default option values */ + +#define DEFAULT_RES 300 +#define DEFAULT_PREVIEW SANE_FALSE +#define DEFAULT_HIGHQUALITY SANE_FALSE +#define DEFAULT_BRIGHTNESS 0 +#define DEFAULT_CONTRAST 0 +#define DEFAULT_GAMMA SANE_FIX(1.8) +#define DEFAULT_HALFTONE SANE_FALSE +#define DEFAULT_NEGATIVE SANE_FALSE +#define DEFAULT_THRESHOLD 50 +#define DEFAULT_QUALITY SANE_TRUE +#define DEFAULT_CUSTOM_GAMMA SANE_FALSE +#define DEFAULT_GAMMA_BIND SANE_FALSE + +static SANE_Int def_rgb_lpr = 4; +static SANE_Int def_gs_lpr = 12; +static SANE_Int def_bpp = 8; +static SANE_Int def_frame_no = 1; + + +/* predefined preview mode name */ +static char md_auto[] = "Auto"; + +/* predefined focus mode name */ +static char md_manual[] = "Manual"; + +/* predefined scan mode names */ +static char md_colour[] = SANE_VALUE_SCAN_MODE_COLOR; +static char md_bilevelcolour[] = SANE_VALUE_SCAN_MODE_HALFTONE; +static char md_greyscale[] = SANE_VALUE_SCAN_MODE_GRAY; +static char md_lineart[] = SANE_VALUE_SCAN_MODE_LINEART; + +/* predefined scan source names */ +static char src_flatbed[] = SANE_I18N("Flatbed"); +static char src_tpo[] = SANE_I18N("Transparency Adapter"); +static char src_adf[] = SANE_I18N("Document Feeder"); + +/* predefined scan window setting names */ +static char pdw_none[] = SANE_I18N("None"); +static char pdw_6X4[] = SANE_I18N("6x4 (inch)"); +static char pdw_8X10[] = SANE_I18N("8x10 (inch)"); +static char pdw_85X11[] = SANE_I18N("8.5x11 (inch)"); + +/* predefined dither matrix names */ +static char dm_none[] = SANE_I18N("Halftoning Unsupported"); +static char dm_dd8x8[] = SANE_I18N("DispersedDot8x8"); +static char dm_dd16x16[] = SANE_I18N("DispersedDot16x16"); + +/* strings */ +static char lpr_desc[] = SANE_I18N( + "Number of scan lines to request in a SCSI read. " + "Changing this parameter allows you to tune the speed at which " + "data is read from the scanner during scans. If this is set too " + "low, the scanner will have to stop periodically in the middle of " + "a scan; if it's set too high, X-based frontends may stop responding " + "to X events and your system could bog down."); + +static char frame_desc[] = SANE_I18N( + "Frame number of media holder that should be scanned."); + +static char focus_mode_desc[] = SANE_I18N( + "Use manual or automatic selection of focus point."); + +static char focus_desc[] = SANE_I18N( + "Focus point for scanning."); + +/* ranges */ +static const SANE_Range x_range_fb = +{ + SANE_FIX (0.0), SANE_FIX (216.0), 0 +}; /* mm */ +static const SANE_Range y_range_fb = +{ + SANE_FIX (0.0), SANE_FIX (297.0), 0 +}; /* mm */ + +/* default TPO range (shortest y_range + to avoid tray collision. +*/ +static const SANE_Range x_range_tpo_default = +{ + SANE_FIX (0.0), SANE_FIX (129.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_default = +{ + SANE_FIX (0.0), SANE_FIX (180.0), 0 +}; /* mm */ + +/* TPO range for the Agfa 1236 */ +static const SANE_Range x_range_tpo_1236 = +{ + SANE_FIX (0.0), SANE_FIX (203.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_1236 = +{ + SANE_FIX (0.0), SANE_FIX (254.0), 0 +}; /* mm */ + +/* TPO range for the Agfa e50 */ +static const SANE_Range x_range_tpo_e50 = +{ + SANE_FIX (0.0), SANE_FIX (40.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_e50 = +{ + SANE_FIX (0.0), SANE_FIX (240.0), 0 +}; /* mm */ + +/* TPO range for the Epson 1670 */ +static const SANE_Range x_range_tpo_1670 = +{ + SANE_FIX (0.0), SANE_FIX (101.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_1670 = +{ + SANE_FIX (0.0), SANE_FIX (228.0), 0 +}; /* mm */ + +/* TPO range for the Epson 2480 */ +static const SANE_Range x_range_tpo_2480 = +{ + SANE_FIX (0.0), SANE_FIX (55.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_2480 = +{ + SANE_FIX (0.0), SANE_FIX (125.0), 0 +}; /* mm */ +/* TPO range for the Epson 2580 */ +static const SANE_Range x_range_tpo_2580 = +{ + SANE_FIX (0.0), SANE_FIX (55.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_2580 = +{ + SANE_FIX (0.0), SANE_FIX (80.0), 0 +}; /* mm */ + +/* TPO range for the Scanwit 2720S */ +static const SANE_Range x_range_tpo_2720s = +{ + SANE_FIX (0.0), SANE_FIX (23.6), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_2720s = +{ + SANE_FIX (0.0), SANE_FIX (35.7), 0 +}; /* mm */ + +/* TPO range for the Epson 3490 */ +static const SANE_Range x_range_tpo_3490 = +{ + SANE_FIX (0.0), SANE_FIX (33.0), 0 +}; /* mm */ +static const SANE_Range y_range_tpo_3490 = +{ + SANE_FIX (0.0), SANE_FIX (162.0), 0 +}; /* mm */ + +static SANE_Range x_range_tpo; +static SANE_Range y_range_tpo; +static const SANE_Range gamma_range = +{ + SANE_FIX (0.0), SANE_FIX (4.0), 0 +}; +static const SANE_Range gamma_vrange = +{ + 0, 65535, 1 +}; +static const SANE_Range lpr_range = +{ + 1, 50, 1 +}; +static const SANE_Range frame_range = +{ + 1, 6, 1 +}; +static const SANE_Range focus_range = +{ + 0, 0x300, 6 +}; + +static const SANE_Range brightness_range = +{ + -400 << SANE_FIXED_SCALE_SHIFT, + 400 << SANE_FIXED_SCALE_SHIFT, + 1 << SANE_FIXED_SCALE_SHIFT +}; + +static const SANE_Range contrast_range = +{ + -100 << SANE_FIXED_SCALE_SHIFT, + 400 << SANE_FIXED_SCALE_SHIFT, + 1 << SANE_FIXED_SCALE_SHIFT +}; + +static const SANE_Range positive_percent_range = +{ + 0 << SANE_FIXED_SCALE_SHIFT, + 100 << SANE_FIXED_SCALE_SHIFT, + 1 << SANE_FIXED_SCALE_SHIFT +}; + +static void control_options(SnapScan_Scanner *pss); + +/* 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_Word resolutions_1200_5000e[] = + {9, 50, 75, 100, 150, 200, 300, 450, 600, 1200}; + static SANE_Word resolutions_1600[] = + {10, 50, 75, 100, 150, 200, 300, 400, 600, 800, 1600}; + static SANE_Word resolutions_2400[] = + {10, 50, 75, 100, 150, 200, 300, 400, 600, 1200, 2400}; + static SANE_Word resolutions_2700[] = + {4, 337, 675, 1350, 2700}; + static SANE_Word resolutions_3200[] = + {15, 50, 150, 200, 240, 266, 300, 350, 360, 400, 600, 720, 800, 1200, 1600, 3200}; + 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}; + static SANE_String_Const focus_modes[] = + {md_auto, md_manual, NULL}; + static SANE_Int bit_depth_list[4]; + int bit_depths; + SANE_Option_Descriptor *po = ps->options; + + /* Initialize TPO range */ + switch (ps->pdev->model) + { + case SNAPSCAN1236: + x_range_tpo = x_range_tpo_1236; + y_range_tpo = y_range_tpo_1236; + break; + case SNAPSCANE20: + case SNAPSCANE50: + case SNAPSCANE52: + x_range_tpo = x_range_tpo_e50; + y_range_tpo = y_range_tpo_e50; + break; + case PERFECTION1270: + case PERFECTION1670: + x_range_tpo = x_range_tpo_1670; + y_range_tpo = y_range_tpo_1670; + break; + case PERFECTION2480: + if (ps->hconfig_epson & 0x20) + { + x_range_tpo = x_range_tpo_2580; + y_range_tpo = y_range_tpo_2580; + } + else + { + x_range_tpo = x_range_tpo_2480; + y_range_tpo = y_range_tpo_2480; + } + break; + case SCANWIT2720S: + x_range_tpo = x_range_tpo_2720s; + y_range_tpo = y_range_tpo_2720s; + break; + case PERFECTION3490: + x_range_tpo = x_range_tpo_3490; + y_range_tpo = y_range_tpo_3490; + break; + default: + x_range_tpo = x_range_tpo_default; + y_range_tpo = y_range_tpo_default; + break; + } + + /* Initialize option descriptors */ + 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; + + ps->res = DEFAULT_RES; + 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 PRISA310: /* WG changed */ + po[OPT_SCANRES].constraint.word_list = resolutions_300; + break; + case SNAPSCANE50: + case SNAPSCANE52: + case PRISA5300: + case PRISA1240: + case ARCUS1200: + po[OPT_SCANRES].constraint.word_list = resolutions_1200; + break; + case PRISA5000E: + case PRISA5000: + case PRISA5150: + po[OPT_SCANRES].constraint.word_list = resolutions_1200_5000e; + break; + case PERFECTION1670: + po[OPT_SCANRES].constraint.word_list = resolutions_1600; + break; + case PERFECTION2480: + po[OPT_SCANRES].constraint.word_list = resolutions_2400; + break; + case PERFECTION3490: + po[OPT_SCANRES].constraint.word_list = resolutions_3200; + break; + case SCANWIT2720S: + po[OPT_SCANRES].constraint.word_list = resolutions_2700; + ps->val[OPT_SCANRES].w = 1350; + ps->res = 1350; + break; + default: + po[OPT_SCANRES].constraint.word_list = resolutions_600; + break; + } + DBG (DL_OPTION_TRACE, + "sane_init_options resolution is %d\n", ps->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_HIGHQUALITY].name = "high-quality"; + po[OPT_HIGHQUALITY].title = SANE_I18N("Quality scan"); + po[OPT_HIGHQUALITY].desc = SANE_I18N("Highest quality but lower speed"); + po[OPT_HIGHQUALITY].type = SANE_TYPE_BOOL; + po[OPT_HIGHQUALITY].unit = SANE_UNIT_NONE; + po[OPT_HIGHQUALITY].size = sizeof (SANE_Word); + po[OPT_HIGHQUALITY].cap = + SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; + po[OPT_HIGHQUALITY].constraint_type = SANE_CONSTRAINT_NONE; + ps->highquality = DEFAULT_HIGHQUALITY; + if (ps->pdev->model == PERFECTION1270) + { + po[OPT_HIGHQUALITY].cap |= SANE_CAP_INACTIVE; + ps->val[OPT_HIGHQUALITY].b = SANE_TRUE; + ps->highquality=SANE_TRUE; + } + + 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 | SANE_CAP_AUTOMATIC; + po[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; + switch (ps->pdev->model) + { + case SNAPSCAN310: + case PRISA310: + case PERFECTION3490: + 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_SOFT_DETECT + | SANE_CAP_ADVANCED + | SANE_CAP_AUTOMATIC; + po[OPT_PREVIEW_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; + switch (ps->pdev->model) + { + case SNAPSCAN310: + case PRISA310: + case PERFECTION3490: + 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_SOFT_DETECT + | SANE_CAP_INACTIVE + | SANE_CAP_AUTOMATIC; + 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; + } + if (ps->hconfig & HCFG_ADF) + { + source_list[i++] = src_adf; + 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; + if (ps->pdev->model == SCANWIT2720S) + { + ps->source = SRC_TPO; + ps->source_s = (SANE_Char *) strdup(src_tpo); + ps->pdev->x_range.max = x_range_tpo.max; + ps->pdev->y_range.max = y_range_tpo.max; + } + else + { + ps->source = SRC_FLATBED; + ps->source_s = (SANE_Char *) strdup(src_flatbed); + } + } + + 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 | SANE_CAP_AUTOMATIC; + 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 | SANE_CAP_AUTOMATIC; + 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 | SANE_CAP_AUTOMATIC; + 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 | SANE_CAP_AUTOMATIC; + 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; + + /* bit depth */ + po[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; + po[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; + po[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; + po[OPT_BIT_DEPTH].type = SANE_TYPE_INT; + po[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; + po[OPT_BIT_DEPTH].size = sizeof (SANE_Word); + po[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; + po[OPT_BIT_DEPTH].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; + bit_depths = 0; + bit_depth_list[++bit_depths] = def_bpp; + switch (ps->pdev->model) + { + case PERFECTION2480: + case PERFECTION3490: + bit_depth_list[++bit_depths] = 16; + break; + case SCANWIT2720S: + bit_depth_list[bit_depths] = 12; + break; + default: + break; + } + bit_depth_list[0] = bit_depths; + po[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list; + if (ps->pdev->model == SCANWIT2720S) + { + ps->val[OPT_BIT_DEPTH].w = 12; + ps->bpp_scan = 12; + } + else + { + ps->val[OPT_BIT_DEPTH].w = def_bpp; + ps->bpp_scan = def_bpp; + } + + 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 and Prisa5300 do not support quality calibration, + although HCFG_CAL_ALLOWED is set. */ + if ((!(ps->hconfig & HCFG_CAL_ALLOWED)) + || (ps->pdev->model == SNAPSCANE52) + || (ps->pdev->model == PERFECTION1670) + || (ps->pdev->model == PRISA5150) + || (ps->pdev->model == PRISA5300)) { + po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; + ps->val[OPT_QUALITY_CAL].b = SANE_FALSE; + } + + if ((ps->pdev->model == PRISA5150) || + (ps->pdev->model == STYLUS_CX1500)) + { + po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; + ps->val[OPT_QUALITY_CAL].b = SANE_TRUE; + } + + 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 | SANE_CAP_AUTOMATIC; + 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_FRAME_NO].name = SANE_I18N("Frame"); + po[OPT_FRAME_NO].title = SANE_I18N("Frame to be scanned"); + po[OPT_FRAME_NO].desc = frame_desc; + po[OPT_FRAME_NO].type = SANE_TYPE_INT; + po[OPT_FRAME_NO].unit = SANE_UNIT_NONE; + po[OPT_FRAME_NO].size = sizeof (SANE_Int); + po[OPT_FRAME_NO].cap = SANE_CAP_SOFT_SELECT + | SANE_CAP_SOFT_DETECT + | SANE_CAP_INACTIVE; + po[OPT_FRAME_NO].constraint_type = SANE_CONSTRAINT_RANGE; + po[OPT_FRAME_NO].constraint.range = &frame_range; + ps->frame_no = def_frame_no; + + po[OPT_FOCUS_MODE].name = SANE_I18N("Focus-mode"); + po[OPT_FOCUS_MODE].title = SANE_I18N("Auto or manual focus"); + po[OPT_FOCUS_MODE].desc = focus_mode_desc; + po[OPT_FOCUS_MODE].type = SANE_TYPE_STRING; + po[OPT_FOCUS_MODE].unit = SANE_UNIT_NONE; + po[OPT_FOCUS_MODE].size = 16; + po[OPT_FOCUS_MODE].cap = SANE_CAP_SOFT_SELECT + | SANE_CAP_SOFT_DETECT + | SANE_CAP_INACTIVE; + po[OPT_FOCUS_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; + po[OPT_FOCUS_MODE].constraint.string_list = focus_modes; + ps->focus_mode_s= md_auto; + ps->focus_mode = MD_AUTO; + + po[OPT_FOCUS_POINT].name = SANE_I18N("Focus-point"); + po[OPT_FOCUS_POINT].title = SANE_I18N("Focus point"); + po[OPT_FOCUS_POINT].desc = focus_desc; + po[OPT_FOCUS_POINT].type = SANE_TYPE_INT; + po[OPT_FOCUS_POINT].unit = SANE_UNIT_NONE; + po[OPT_FOCUS_POINT].size = sizeof (SANE_Int); + po[OPT_FOCUS_POINT].cap = SANE_CAP_SOFT_SELECT + | SANE_CAP_SOFT_DETECT + | SANE_CAP_INACTIVE; + po[OPT_FOCUS_POINT].constraint_type = SANE_CONSTRAINT_RANGE; + po[OPT_FOCUS_POINT].constraint.range = &focus_range; + + 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 | SANE_CAP_AUTOMATIC; + 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 + | SANE_CAP_AUTOMATIC; + po[OPT_GS_LPR].constraint_type = SANE_CONSTRAINT_RANGE; + po[OPT_GS_LPR].constraint.range = &lpr_range; + ps->gs_lpr = def_gs_lpr; + control_options(ps); +} + +const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h, + SANE_Int n) +{ + DBG (DL_OPTION_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; + pss->options[OPT_BIT_DEPTH].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; + } + } + if ((pss->mode == MD_GREYSCALE) || (pss->mode == MD_COLOUR)) + { + switch(pss->pdev->model) + { + case PERFECTION2480: + case PERFECTION3490: + pss->options[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; + break; + default: + break; + } + } + if (pss->pdev->model == SCANWIT2720S) + { + pss->options[OPT_FRAME_NO].cap &= ~SANE_CAP_INACTIVE; + pss->options[OPT_FOCUS_MODE].cap &= ~SANE_CAP_INACTIVE; + if (pss->focus_mode == MD_MANUAL) + { + pss->options[OPT_FOCUS_POINT].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_OPTION_TRACE, + "%s (%p, %ld, %ld, %p, %p)\n", + me, + (void *) h, + (long) n, + (long) a, + v, + (void *) i); + + 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_HIGHQUALITY: + *(SANE_Bool *) v = pss->highquality; + 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; + case OPT_BIT_DEPTH: + *(SANE_Int *) v = pss->val[OPT_BIT_DEPTH].w; + break; + case OPT_FRAME_NO: + *(SANE_Int *) v = pss->frame_no; + break; + case OPT_FOCUS_MODE: + strcpy ((SANE_String) v, pss->focus_mode_s); + break; + case OPT_FOCUS_POINT: + *(SANE_Int *) v = pss->focus; + 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; + } + /* prevent setting of options during a scan */ + if ((pss->state==ST_SCAN_INIT) || (pss->state==ST_SCANNING)) { + DBG(DL_INFO, + "set value for option %s ignored: scanner is still scanning (status %d)\n", + pss->options[n].name, + pss->state + ); + return SANE_STATUS_DEVICE_BUSY; + } + 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_HIGHQUALITY: + pss->highquality = *(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); + } + 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 if (strcmp(v, src_adf) == 0) + { + pss->source = SRC_ADF; + pss->pdev->x_range.max = x_range_fb.max; + pss->pdev->y_range.max = y_range_fb.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; + if (pss->bry > pss->pdev->y_range.max) + pss->bry = pss->pdev->y_range.max; + 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 (pss->tlx > pdev->x_range.max) { + pss->tlx = pdev->x_range.max; + } + if (pss->brx < pss->tlx) { + pss->brx = pss->tlx; + } + if (i) + *i |= SANE_INFO_RELOAD_PARAMS; + break; + case OPT_TLY: + pss->tly = *(SANE_Fixed *) v; + pss->predef_window = pdw_none; + if (pss->tly > pdev->y_range.max){ + pss->tly = pdev->y_range.max; + } + if (pss->bry < pss->tly) { + pss->bry = pss->tly; + } + if (i) + *i |= SANE_INFO_RELOAD_PARAMS; + break; + case OPT_BRX: + pss->brx = *(SANE_Fixed *) v; + pss->predef_window = pdw_none; + if (pss->brx < pdev->x_range.min) { + pss->brx = pdev->x_range.min; + } + if (pss->brx < pss->tlx) { + pss->tlx = pss->brx; + } + if (i) + *i |= SANE_INFO_RELOAD_PARAMS; + break; + case OPT_BRY: + pss->bry = *(SANE_Fixed *) v; + pss->predef_window = pdw_none; + if (pss->bry < pdev->y_range.min) { + pss->bry = pdev->y_range.min; + } + if (pss->bry < pss->tly) { + pss->tly = pss->bry; + } + if (i) + *i |= SANE_INFO_RELOAD_PARAMS; + break; + case OPT_BRIGHTNESS: + pss->bright = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; + break; + case OPT_CONTRAST: + pss->contrast = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; + 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; + break; + case OPT_GAMMA_R: + pss->gamma_r = *(SANE_Fixed *) v; + break; + case OPT_GAMMA_G: + pss->gamma_g = *(SANE_Fixed *) v; + break; + case OPT_GAMMA_B: + pss->gamma_b = *(SANE_Fixed *) v; + break; + case OPT_QUALITY_CAL: + pss->val[n].b = *(SANE_Bool *)v; + 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); + 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); + } + } + break; + case OPT_NEGATIVE: + pss->negative = *(SANE_Bool *) v; + break; + case OPT_THRESHOLD: + pss->threshold = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; + break; + case OPT_RGB_LPR: + pss->rgb_lpr = *(SANE_Int *) v; + break; + case OPT_GS_LPR: + pss->gs_lpr = *(SANE_Int *) v; + break; + case OPT_BIT_DEPTH: + pss->val[OPT_BIT_DEPTH].w = *(SANE_Int *) v; + if (i) + *i |= SANE_INFO_RELOAD_PARAMS; + break; + case OPT_FRAME_NO: + pss->frame_no = *(SANE_Int *) v; + break; + case OPT_FOCUS_MODE: + { + char *s = (SANE_String) v; + if (strcmp (s, md_manual) == 0) + { + pss->focus_mode_s = md_manual; + pss->focus_mode = MD_MANUAL; + pss->options[OPT_FOCUS_POINT].cap &= ~SANE_CAP_INACTIVE; + } + else + { + pss->focus_mode_s = md_auto; + pss->focus_mode = MD_AUTO; + pss->options[OPT_FOCUS_POINT].cap |= SANE_CAP_INACTIVE; + } + if (i) + *i = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; + break; + } + case OPT_FOCUS_POINT: + pss->focus = *(SANE_Int *) v; + break; + default: + DBG (DL_MAJOR_ERROR, + "%s: invalid option number %ld\n", + me, + (long) n); + return SANE_STATUS_UNSUPPORTED; + } + DBG (DL_OPTION_TRACE, "%s: option %s set to value ", + me, pss->options[n].name); + switch (pss->options[n].type) + { + case SANE_TYPE_INT: + DBG (DL_OPTION_TRACE, "%ld\n", (long) (*(SANE_Int *) v)); + break; + case SANE_TYPE_BOOL: + { + char *valstr = (*(SANE_Bool *) v == SANE_TRUE) ? "TRUE" : "FALSE"; + DBG (DL_OPTION_TRACE, "%s\n", valstr); + } + break; + default: + DBG (DL_OPTION_TRACE, "other than an integer or boolean.\n"); + break; + } + break; + case SANE_ACTION_SET_AUTO: + if (i) + *i = 0; + switch (n) + { + case OPT_SCANRES: + if (pss->pdev->model == SCANWIT2720S) + { + pss->res = 1350; + } + else + { + 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_HIGHQUALITY: + pss->highquality = 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; + break; + case OPT_SOURCE: + if (pss->pdev->model == SCANWIT2720S) + { + pss->source = SRC_TPO; + pss->pdev->x_range.max = x_range_tpo.max; + pss->pdev->y_range.max = y_range_tpo.max; + pss->predef_window = pdw_none; + if (pss->source_s) + free (pss->source_s); + pss->source_s = (SANE_Char *) strdup(src_tpo); + } + else + { + pss->source = SRC_FLATBED; + pss->pdev->x_range.max = x_range_fb.max; + pss->pdev->y_range.max = y_range_fb.max; + pss->predef_window = pdw_none; + if (pss->source_s) + free (pss->source_s); + pss->source_s = (SANE_Char *) strdup(src_flatbed); + } + if (i) + *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + 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_NEGATIVE: + pss->negative = DEFAULT_NEGATIVE; + break; + case OPT_RGB_LPR: + pss->rgb_lpr = def_rgb_lpr; + break; + case OPT_GS_LPR: + pss->gs_lpr = def_gs_lpr; + break; + case OPT_BIT_DEPTH: + if (pss->pdev->model == SCANWIT2720S) + { + pss->val[OPT_BIT_DEPTH].w = 12; + } + else + { + pss->val[OPT_BIT_DEPTH].w = def_bpp; + } + break; + case OPT_FRAME_NO: + pss->frame_no = def_frame_no; + break; + case OPT_FOCUS_MODE: + pss->focus_mode_s = md_auto; + pss->focus_mode = MD_AUTO; + if (i) + *i = SANE_INFO_RELOAD_OPTIONS; + break; + case OPT_FOCUS_POINT: + pss->focus = 0x13e; + 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; + } + return SANE_STATUS_GOOD; +} + +/* + * $Log$ + * Revision 1.35 2006/01/06 20:59:17 oliver-guest + * Some fixes for the Epson Stylus CX 1500 + * + * Revision 1.34 2006/01/01 22:57:01 oliver-guest + * Added calibration data for Benq 5150 / 5250, preliminary support for Epson Stylus CX 1500 + * + * Revision 1.33 2005/12/04 15:03:00 oliver-guest + * Some fixes for Benq 5150 + * + * Revision 1.32 2005/11/23 20:57:01 oliver-guest + * Disable bilevel colour / halftoning for Epson 3490 + * + * Revision 1.31 2005/11/17 23:47:10 oliver-guest + * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead + * + * Revision 1.30 2005/11/15 20:11:18 oliver-guest + * Enabled quality calibration for the Epson 3490 + * + * Revision 1.29 2005/10/31 21:08:47 oliver-guest + * Distinguish between Benq 5000/5000E/5000U + * + * Revision 1.28 2005/10/24 19:46:40 oliver-guest + * Preview and range fix for Epson 2480/2580 + * + * Revision 1.27 2005/10/13 22:43:30 oliver-guest + * Fixes for 16 bit scan mode from Simon Munton + * + * Revision 1.26 2005/10/11 18:47:07 oliver-guest + * Fixes for Epson 3490 and 16 bit scan mode + * + * Revision 1.25 2005/09/28 22:09:26 oliver-guest + * Reenabled enhanced inquiry command for Epson scanners (duh\!) + * + * Revision 1.24 2005/09/28 21:33:10 oliver-guest + * Added 16 bit option for Epson scanners (untested) + * + * Revision 1.23 2005/08/16 20:15:10 oliver-guest + * Removed C++-style comment + * + * Revision 1.22 2005/08/15 18:06:37 oliver-guest + * Added support for Epson 3490/3590 (thanks to Matt Judge) + * + * Revision 1.21 2005/07/20 21:37:29 oliver-guest + * Changed TPO scanning area for 2480/2580, reenabled 2400 DPI for 2480/2580 + * + * Revision 1.20 2005/05/22 11:50:24 oliver-guest + * Disabled 2400 DPI for Epson 2480 + * + * Revision 1.19 2004/12/09 23:21:47 oliver-guest + * Added quality calibration for Epson 2480 (by Simon Munton) + * + * Revision 1.18 2004/12/01 22:12:02 oliver-guest + * Added support for Epson 1270 + * + * Revision 1.17 2004/09/02 20:59:11 oliver-guest + * Added support for Epson 2480 + * + * Revision 1.16 2004/04/08 21:53:10 oliver-guest + * Use sanei_thread in snapscan backend + * + * Revision 1.15 2004/04/02 20:19:23 oliver-guest + * Various bugfixes for gamma corretion (thanks to Robert Tsien) + * + * Revision 1.14 2004/02/01 13:32:26 oliver-guest + * Fixed resolutions for Epson 1670 + * + * Revision 1.13 2003/11/28 23:23:18 oliver-guest + * Correct length of wordlist for resolutions_1600 + * + * Revision 1.12 2003/11/09 21:43:45 oliver-guest + * Disabled quality calibration for Epson Perfection 1670 + * + * Revision 1.11 2003/11/08 09:50:27 oliver-guest + * Fix TPO scanning range for Epson 1670 + * + * Revision 1.10 2003/10/21 20:43:25 oliver-guest + * Bugfixes for SnapScan backend + * + * Revision 1.9 2003/10/07 18:29:20 oliver-guest + * Initial support for Epson 1670, minor bugfix + * + * Revision 1.8 2003/08/19 21:05:08 oliverschwartz + * Scanner ID cleanup + * + * Revision 1.7 2003/04/30 20:49:39 oliverschwartz + * SnapScan backend 1.4.26 + * + * Revision 1.8 2003/04/30 20:42:18 oliverschwartz + * Added support for Agfa Arcus 1200 (supplied by Valtteri Vuorikoski) + * + * Revision 1.7 2003/04/02 21:17:12 oliverschwartz + * Fix for 1200 DPI with Acer 5000 + * + * Revision 1.6 2002/07/12 23:23:06 oliverschwartz + * Disable quality calibration for 5300 + * + * Revision 1.5 2002/06/06 20:40:00 oliverschwartz + * Changed default scan area for transparancy unit of SnapScan e50 + * + * Revision 1.4 2002/05/02 18:28:44 oliverschwartz + * Added ADF support + * + * Revision 1.3 2002/04/27 14:43:59 oliverschwartz + * - Remove SCSI debug options + * - Fix option handling (errors detected by tstbackend) + * + * Revision 1.2 2002/04/23 22:50:24 oliverschwartz + * Improve handling of scan area options + * + * Revision 1.1 2002/03/24 12:07:15 oliverschwartz + * Moved option functions from snapscan.c to snapscan-options.c + * + * + * */ |