• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 1997, 1998, 2001, 2013 Franck Schnefra, Michel Roelofs,
4    Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
5    Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson,
6    Andrew Goodbody, Oliver Schwartz and Kevin Charter
7 
8    This file is part of the SANE package.
9 
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of the
13    License, or (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <https://www.gnu.org/licenses/>.
22 
23    As a special exception, the authors of SANE give permission for
24    additional uses of the libraries contained in this release of SANE.
25 
26    The exception is that, if you link a SANE library with other files
27    to produce an executable, this does not by itself cause the
28    resulting executable to be covered by the GNU General Public
29    License.  Your use of that executable is in no way restricted on
30    account of linking the SANE library code into it.
31 
32    This exception does not, however, invalidate any other reasons why
33    the executable file might be covered by the GNU General Public
34    License.
35 
36    If you submit changes to SANE to the maintainers to be included in
37    a subsequent release, you agree by submitting the changes that
38    those changes may be distributed with this exception intact.
39 
40    If you write modifications of your own for SANE, it is your choice
41    whether to permit this exception to apply to your modifications.
42    If you do not wish that, delete this exception notice.
43 
44    This file is a component of the implementation of a backend for many
45    of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners.
46 */
47 
48 /*
49    SANE SnapScan backend
50 */
51 
52 /* default option values */
53 
54 #define DEFAULT_RES             300
55 #define DEFAULT_PREVIEW         SANE_FALSE
56 #define DEFAULT_HIGHQUALITY     SANE_FALSE
57 #define DEFAULT_BRIGHTNESS      0
58 #define DEFAULT_CONTRAST        0
59 #define DEFAULT_GAMMA           SANE_FIX(1.8)
60 #define DEFAULT_HALFTONE        SANE_FALSE
61 #define DEFAULT_NEGATIVE        SANE_FALSE
62 #define DEFAULT_THRESHOLD       50
63 #define DEFAULT_QUALITY         SANE_TRUE
64 #define DEFAULT_CUSTOM_GAMMA    SANE_FALSE
65 #define DEFAULT_GAMMA_BIND      SANE_FALSE
66 
67 static SANE_Int def_rgb_lpr = 4;
68 static SANE_Int def_gs_lpr = 12;
69 static SANE_Int def_bpp = 8;
70 static SANE_Int def_frame_no = 1;
71 
72 
73 /* predefined preview mode name */
74 static char md_auto[] = "Auto";
75 
76 /* predefined focus mode name */
77 static char md_manual[] = "Manual";
78 
79 /* predefined scan mode names */
80 static char md_colour[] = SANE_VALUE_SCAN_MODE_COLOR;
81 static char md_bilevelcolour[] = SANE_VALUE_SCAN_MODE_HALFTONE;
82 static char md_greyscale[] = SANE_VALUE_SCAN_MODE_GRAY;
83 static char md_lineart[] = SANE_VALUE_SCAN_MODE_LINEART;
84 
85 /* predefined scan source names */
86 static char src_flatbed[] = SANE_I18N("Flatbed");
87 static char src_tpo[] = SANE_I18N("Transparency Adapter");
88 static char src_adf[] = SANE_I18N("Document Feeder");
89 
90 /* predefined scan window setting names */
91 static char pdw_none[] = SANE_I18N("None");
92 static char pdw_6X4[] = SANE_I18N("6x4 (inch)");
93 static char pdw_8X10[] = SANE_I18N("8x10 (inch)");
94 static char pdw_85X11[] = SANE_I18N("8.5x11 (inch)");
95 
96 /* predefined dither matrix names */
97 static char dm_none[] = SANE_I18N("Halftoning Unsupported");
98 static char dm_dd8x8[] = SANE_I18N("DispersedDot8x8");
99 static char dm_dd16x16[] = SANE_I18N("DispersedDot16x16");
100 
101 /* strings */
102 static char lpr_desc[] = SANE_I18N(
103     "Number of scan lines to request in a SCSI read. "
104     "Changing this parameter allows you to tune the speed at which "
105     "data is read from the scanner during scans. If this is set too "
106     "low, the scanner will have to stop periodically in the middle of "
107     "a scan; if it's set too high, X-based frontends may stop responding "
108     "to X events and your system could bog down.");
109 
110 static char frame_desc[] = SANE_I18N(
111     "Frame number of media holder that should be scanned.");
112 
113 static char focus_mode_desc[] = SANE_I18N(
114     "Use manual or automatic selection of focus point.");
115 
116 static char focus_desc[] = SANE_I18N(
117     "Focus point for scanning.");
118 
119 /* ranges */
120 static const SANE_Range x_range_fb =
121 {
122     SANE_FIX (0.0), SANE_FIX (216.0), 0
123 };        /* mm */
124 static const SANE_Range y_range_fb =
125 {
126     SANE_FIX (0.0), SANE_FIX (297.0), 0
127 };        /* mm */
128 
129 /* default TPO range (shortest y_range
130    to avoid tray collision.
131 */
132 static const SANE_Range x_range_tpo_default =
133 {
134     SANE_FIX (0.0), SANE_FIX (129.0), 0
135 };        /* mm */
136 static const SANE_Range y_range_tpo_default =
137 {
138     SANE_FIX (0.0), SANE_FIX (180.0), 0
139 };        /* mm */
140 
141 /* TPO range for the Agfa Arcus 1200 */
142 static const SANE_Range x_range_tpo_arcus =
143 {
144     SANE_FIX (0.0), SANE_FIX (203.0), 0
145 };        /* mm */
146 static const SANE_Range y_range_tpo_arcus =
147 {
148     SANE_FIX (0.0), SANE_FIX (254.0), 0
149 };        /* mm */
150 
151 /* TPO range for the Agfa 1236 */
152 static const SANE_Range x_range_tpo_1236 =
153 {
154     SANE_FIX (0.0), SANE_FIX (203.0), 0
155 };        /* mm */
156 static const SANE_Range y_range_tpo_1236 =
157 {
158     SANE_FIX (0.0), SANE_FIX (254.0), 0
159 };        /* mm */
160 
161 /* TPO range for the Agfa e50 */
162 static const SANE_Range x_range_tpo_e50 =
163 {
164     SANE_FIX (0.0), SANE_FIX (40.0), 0
165 };        /* mm */
166 static const SANE_Range y_range_tpo_e50 =
167 {
168     SANE_FIX (0.0), SANE_FIX (240.0), 0
169 };        /* mm */
170 
171 /* TPO range for the Epson 1670 */
172 static const SANE_Range x_range_tpo_1670 =
173 {
174     SANE_FIX (0.0), SANE_FIX (101.0), 0
175 };        /* mm */
176 static const SANE_Range y_range_tpo_1670 =
177 {
178     SANE_FIX (0.0), SANE_FIX (228.0), 0
179 };        /* mm */
180 
181 /* TPO range for the Epson 2480 */
182 static const SANE_Range x_range_tpo_2480 =
183 {
184     SANE_FIX (0.0), SANE_FIX (55.0), 0
185 };        /* mm */
186 static const SANE_Range y_range_tpo_2480 =
187 {
188     SANE_FIX (0.0), SANE_FIX (125.0), 0
189 };        /* mm */
190 /* TPO range for the Epson 2580 */
191 static const SANE_Range x_range_tpo_2580 =
192 {
193     SANE_FIX (0.0), SANE_FIX (55.0), 0
194 };        /* mm */
195 static const SANE_Range y_range_tpo_2580 =
196 {
197     SANE_FIX (0.0), SANE_FIX (80.0), 0
198 };        /* mm */
199 
200 /* TPO range for the Scanwit 2720S */
201 static const SANE_Range x_range_tpo_2720s =
202 {
203     SANE_FIX (0.0), SANE_FIX (23.6), 0
204 };        /* mm */
205 static const SANE_Range y_range_tpo_2720s =
206 {
207     SANE_FIX (0.0), SANE_FIX (35.7), 0
208 };        /* mm */
209 
210 /* TPO range for the Epson 3490 */
211 static const SANE_Range x_range_tpo_3490 =
212 {
213     SANE_FIX (0.0), SANE_FIX (33.0), 0
214 };        /* mm */
215 static const SANE_Range y_range_tpo_3490 =
216 {
217     SANE_FIX (0.0), SANE_FIX (162.0), 0
218 };        /* mm */
219 
220 static SANE_Range x_range_tpo;
221 static SANE_Range y_range_tpo;
222 static const SANE_Range gamma_range =
223 {
224     SANE_FIX (0.0), SANE_FIX (4.0), 0
225 };
226 static const SANE_Range gamma_vrange =
227 {
228     0, 65535, 1
229 };
230 static const SANE_Range lpr_range =
231 {
232     1, 50, 1
233 };
234 static const SANE_Range frame_range =
235 {
236     1, 6, 1
237 };
238 static const SANE_Range focus_range =
239 {
240     0, 0x300, 6
241 };
242 
243 static const SANE_Range brightness_range =
244 {
245     SANE_FIX(-400),
246     SANE_FIX(400),
247     SANE_FIX(1)
248 };
249 
250 static const SANE_Range contrast_range =
251 {
252     SANE_FIX(-100),
253     SANE_FIX(400),
254     SANE_FIX(1)
255 };
256 
257 static const SANE_Range positive_percent_range =
258 {
259     SANE_FIX(0),
260     SANE_FIX(100),
261     SANE_FIX(1)
262 };
263 
264 static void control_options(SnapScan_Scanner *pss);
265 
266 /* init_options -- initialize the option set for a scanner; expects the
267    scanner structure's hardware configuration byte (hconfig) to be valid.
268 
269    ARGS: a pointer to an existing scanner structure
270    RET:  nothing
271    SIDE: the option set of *ps is initialized; this includes both
272    the option descriptors and the option values themselves */
init_options(SnapScan_Scanner * ps)273 static void init_options (SnapScan_Scanner * ps)
274 {
275     static SANE_Word resolutions_300[] =
276         {6, 50, 75, 100, 150, 200, 300};
277     static SANE_Word resolutions_600[] =
278         {8, 50, 75, 100, 150, 200, 300, 450, 600};
279     static SANE_Word resolutions_1200[] =
280         {10, 50, 75, 100, 150, 200, 300, 450, 600, 900, 1200};
281     static SANE_Word resolutions_1200_5000e[] =
282         {9, 50, 75, 100, 150, 200, 300, 450, 600, 1200};
283     static SANE_Word resolutions_1600[] =
284         {10, 50, 75, 100, 150, 200, 300, 400, 600, 800, 1600};
285     static SANE_Word resolutions_2400[] =
286         {10, 50, 75, 100, 150, 200, 300, 400, 600, 1200, 2400};
287     static SANE_Word resolutions_2700[] =
288         {4, 337, 675, 1350, 2700};
289     static SANE_Word resolutions_3200[] =
290         {15, 50, 150, 200, 240, 266, 300, 350, 360, 400, 600, 720, 800, 1200, 1600, 3200};
291     static SANE_String_Const names_all[] =
292         {md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
293     static SANE_String_Const names_basic[] =
294         {md_colour, md_greyscale, md_lineart, NULL};
295     static SANE_String_Const preview_names_all[] =
296         {md_auto, md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
297     static SANE_String_Const preview_names_basic[] =
298         {md_auto, md_colour, md_greyscale, md_lineart, NULL};
299     static SANE_String_Const focus_modes[] =
300         {md_auto, md_manual, NULL};
301     static SANE_Int bit_depth_list[4];
302     int bit_depths;
303     SANE_Option_Descriptor *po = ps->options;
304 
305     /* Initialize TPO range */
306     switch (ps->pdev->model)
307     {
308     case SNAPSCAN1236:
309         x_range_tpo = x_range_tpo_1236;
310         y_range_tpo = y_range_tpo_1236;
311         break;
312     case SNAPSCANE20:
313     case SNAPSCANE50:
314     case SNAPSCANE52:
315         x_range_tpo = x_range_tpo_e50;
316         y_range_tpo = y_range_tpo_e50;
317         break;
318     case PERFECTION1270:
319     case PERFECTION1670:
320         x_range_tpo = x_range_tpo_1670;
321         y_range_tpo = y_range_tpo_1670;
322         break;
323     case PERFECTION2480:
324         if (ps->hconfig_epson & 0x20)
325         {
326            x_range_tpo = x_range_tpo_2580;
327            y_range_tpo = y_range_tpo_2580;
328         }
329         else
330         {
331            x_range_tpo = x_range_tpo_2480;
332            y_range_tpo = y_range_tpo_2480;
333         }
334         break;
335     case SCANWIT2720S:
336         x_range_tpo = x_range_tpo_2720s;
337         y_range_tpo = y_range_tpo_2720s;
338         break;
339     case PERFECTION3490:
340         x_range_tpo = x_range_tpo_3490;
341         y_range_tpo = y_range_tpo_3490;
342         break;
343     case ARCUS1200:
344         x_range_tpo = x_range_tpo_arcus;
345         y_range_tpo = y_range_tpo_arcus;
346         break;
347     default:
348         x_range_tpo = x_range_tpo_default;
349         y_range_tpo = y_range_tpo_default;
350         break;
351     }
352 
353 	/* Initialize option descriptors */
354     po[OPT_COUNT].name = SANE_NAME_NUM_OPTIONS;
355     po[OPT_COUNT].title = SANE_TITLE_NUM_OPTIONS;
356     po[OPT_COUNT].desc = SANE_DESC_NUM_OPTIONS;
357     po[OPT_COUNT].type = SANE_TYPE_INT;
358     po[OPT_COUNT].unit = SANE_UNIT_NONE;
359     po[OPT_COUNT].size = sizeof (SANE_Word);
360     po[OPT_COUNT].cap = SANE_CAP_SOFT_DETECT;
361     {
362         static SANE_Range count_range =
363             {NUM_OPTS, NUM_OPTS, 0};
364         po[OPT_COUNT].constraint_type = SANE_CONSTRAINT_RANGE;
365         po[OPT_COUNT].constraint.range = &count_range;
366     }
367 
368     po[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
369     po[OPT_MODE_GROUP].desc = "";
370     po[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
371     po[OPT_MODE_GROUP].cap = 0;
372     po[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
373 
374     ps->res = DEFAULT_RES;
375     po[OPT_SCANRES].name = SANE_NAME_SCAN_RESOLUTION;
376     po[OPT_SCANRES].title = SANE_TITLE_SCAN_RESOLUTION;
377     po[OPT_SCANRES].desc = SANE_DESC_SCAN_RESOLUTION;
378     po[OPT_SCANRES].type = SANE_TYPE_INT;
379     po[OPT_SCANRES].unit = SANE_UNIT_DPI;
380     po[OPT_SCANRES].size = sizeof (SANE_Word);
381     po[OPT_SCANRES].cap =
382         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
383     po[OPT_SCANRES].constraint_type = SANE_CONSTRAINT_WORD_LIST;
384     switch (ps->pdev->model)
385     {
386     case SNAPSCAN310:
387     case PRISA310:                /* WG changed */
388         po[OPT_SCANRES].constraint.word_list = resolutions_300;
389         break;
390     case SNAPSCANE50:
391     case SNAPSCANE52:
392     case PRISA5300:
393     case PRISA1240:
394     case ARCUS1200:
395         po[OPT_SCANRES].constraint.word_list = resolutions_1200;
396         break;
397     case PRISA5000E:
398     case PRISA5000:
399     case PRISA5150:
400         po[OPT_SCANRES].constraint.word_list = resolutions_1200_5000e;
401         break;
402     case PERFECTION1670:
403         po[OPT_SCANRES].constraint.word_list = resolutions_1600;
404         break;
405     case PERFECTION2480:
406         po[OPT_SCANRES].constraint.word_list = resolutions_2400;
407         break;
408     case PERFECTION3490:
409         po[OPT_SCANRES].constraint.word_list = resolutions_3200;
410         break;
411     case SCANWIT2720S:
412         po[OPT_SCANRES].constraint.word_list = resolutions_2700;
413         ps->val[OPT_SCANRES].w = 1350;
414         ps->res = 1350;
415         break;
416     default:
417         po[OPT_SCANRES].constraint.word_list = resolutions_600;
418         break;
419     }
420     DBG (DL_OPTION_TRACE,
421         "sane_init_options resolution is %d\n", ps->res);
422 
423     po[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
424     po[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
425     po[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
426     po[OPT_PREVIEW].type = SANE_TYPE_BOOL;
427     po[OPT_PREVIEW].unit = SANE_UNIT_NONE;
428     po[OPT_PREVIEW].size = sizeof (SANE_Word);
429     po[OPT_PREVIEW].cap =
430         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
431     po[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
432     ps->preview = DEFAULT_PREVIEW;
433 
434     po[OPT_HIGHQUALITY].name = "high-quality";
435     po[OPT_HIGHQUALITY].title = SANE_I18N("Quality scan");
436     po[OPT_HIGHQUALITY].desc = SANE_I18N("Highest quality but lower speed");
437     po[OPT_HIGHQUALITY].type = SANE_TYPE_BOOL;
438     po[OPT_HIGHQUALITY].unit = SANE_UNIT_NONE;
439     po[OPT_HIGHQUALITY].size = sizeof (SANE_Word);
440     po[OPT_HIGHQUALITY].cap =
441         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
442     po[OPT_HIGHQUALITY].constraint_type = SANE_CONSTRAINT_NONE;
443     ps->highquality = DEFAULT_HIGHQUALITY;
444     if (ps->pdev->model == PERFECTION1270)
445     {
446         po[OPT_HIGHQUALITY].cap |= SANE_CAP_INACTIVE;
447         ps->val[OPT_HIGHQUALITY].b = SANE_TRUE;
448         ps->highquality=SANE_TRUE;
449     }
450 
451     po[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
452     po[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
453     po[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
454     po[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
455     po[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
456     po[OPT_BRIGHTNESS].size = sizeof (int);
457     po[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
458     po[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
459     po[OPT_BRIGHTNESS].constraint.range = &brightness_range;
460     ps->bright = DEFAULT_BRIGHTNESS;
461 
462     po[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
463     po[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
464     po[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
465     po[OPT_CONTRAST].type = SANE_TYPE_FIXED;
466     po[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
467     po[OPT_CONTRAST].size = sizeof (int);
468     po[OPT_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
469     po[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
470     po[OPT_CONTRAST].constraint.range = &contrast_range;
471     ps->contrast = DEFAULT_CONTRAST;
472 
473     po[OPT_MODE].name = SANE_NAME_SCAN_MODE;
474     po[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
475     po[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
476     po[OPT_MODE].type = SANE_TYPE_STRING;
477     po[OPT_MODE].unit = SANE_UNIT_NONE;
478     po[OPT_MODE].size = 32;
479     po[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
480     po[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
481     switch (ps->pdev->model)
482     {
483     case SNAPSCAN310:
484     case PRISA310:
485     case PERFECTION3490:
486         po[OPT_MODE].constraint.string_list = names_basic;
487         break;
488     default:
489         po[OPT_MODE].constraint.string_list = names_all;
490         break;
491     }
492     ps->mode_s = md_colour;
493     ps->mode = MD_COLOUR;
494 
495     po[OPT_PREVIEW_MODE].name = "preview-mode";
496     po[OPT_PREVIEW_MODE].title = SANE_I18N("Preview mode");
497     po[OPT_PREVIEW_MODE].desc = SANE_I18N(
498         "Select the mode for previews. Greyscale previews usually give "
499         "the best combination of speed and detail.");
500     po[OPT_PREVIEW_MODE].type = SANE_TYPE_STRING;
501     po[OPT_PREVIEW_MODE].unit = SANE_UNIT_NONE;
502     po[OPT_PREVIEW_MODE].size = 32;
503     po[OPT_PREVIEW_MODE].cap = SANE_CAP_SOFT_SELECT
504                                | SANE_CAP_SOFT_DETECT
505                                | SANE_CAP_ADVANCED
506                                | SANE_CAP_AUTOMATIC;
507     po[OPT_PREVIEW_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
508     switch (ps->pdev->model)
509     {
510     case SNAPSCAN310:
511     case PRISA310:
512     case PERFECTION3490:
513         po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_basic;
514         break;
515     default:
516         po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_all;
517         break;
518     }
519     ps->preview_mode_s = md_auto;
520     ps->preview_mode = ps->mode;
521 
522     /* source */
523     po[OPT_SOURCE].name  = SANE_NAME_SCAN_SOURCE;
524     po[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
525     po[OPT_SOURCE].desc  = SANE_DESC_SCAN_SOURCE;
526     po[OPT_SOURCE].type  = SANE_TYPE_STRING;
527     po[OPT_SOURCE].cap   = SANE_CAP_SOFT_SELECT
528                            | SANE_CAP_SOFT_DETECT
529                            | SANE_CAP_INACTIVE
530                            | SANE_CAP_AUTOMATIC;
531     po[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
532     {
533         static SANE_String_Const source_list[3];
534         int i = 0;
535 
536         source_list[i++]= src_flatbed;
537         if (ps->hconfig & HCFG_TPO)
538         {
539             source_list[i++] = src_tpo;
540             po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
541         }
542         if (ps->hconfig & HCFG_ADF)
543         {
544             source_list[i++] = src_adf;
545             po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
546         }
547         source_list[i] = 0;
548         po[OPT_SOURCE].size = max_string_size(source_list);
549         po[OPT_SOURCE].constraint.string_list = source_list;
550         if (ps->pdev->model == SCANWIT2720S)
551         {
552             ps->source = SRC_TPO;
553             ps->source_s = (SANE_Char *) strdup(src_tpo);
554             ps->pdev->x_range.max = x_range_tpo.max;
555             ps->pdev->y_range.max = y_range_tpo.max;
556         }
557         else
558         {
559             ps->source = SRC_FLATBED;
560             ps->source_s = (SANE_Char *) strdup(src_flatbed);
561         }
562     }
563 
564     po[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry");
565     po[OPT_GEOMETRY_GROUP].desc = "";
566     po[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
567     po[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
568     po[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
569 
570     po[OPT_TLX].name = SANE_NAME_SCAN_TL_X;
571     po[OPT_TLX].title = SANE_TITLE_SCAN_TL_X;
572     po[OPT_TLX].desc = SANE_DESC_SCAN_TL_X;
573     po[OPT_TLX].type = SANE_TYPE_FIXED;
574     po[OPT_TLX].unit = SANE_UNIT_MM;
575     po[OPT_TLX].size = sizeof (SANE_Word);
576     po[OPT_TLX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
577     po[OPT_TLX].constraint_type = SANE_CONSTRAINT_RANGE;
578     po[OPT_TLX].constraint.range = &(ps->pdev->x_range);
579     ps->tlx = ps->pdev->x_range.min;
580 
581     po[OPT_TLY].name = SANE_NAME_SCAN_TL_Y;
582     po[OPT_TLY].title = SANE_TITLE_SCAN_TL_Y;
583     po[OPT_TLY].desc = SANE_DESC_SCAN_TL_Y;
584     po[OPT_TLY].type = SANE_TYPE_FIXED;
585     po[OPT_TLY].unit = SANE_UNIT_MM;
586     po[OPT_TLY].size = sizeof (SANE_Word);
587     po[OPT_TLY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
588     po[OPT_TLY].constraint_type = SANE_CONSTRAINT_RANGE;
589     po[OPT_TLY].constraint.range = &(ps->pdev->y_range);
590     ps->tly = ps->pdev->y_range.min;
591 
592     po[OPT_BRX].name = SANE_NAME_SCAN_BR_X;
593     po[OPT_BRX].title = SANE_TITLE_SCAN_BR_X;
594     po[OPT_BRX].desc = SANE_DESC_SCAN_BR_X;
595     po[OPT_BRX].type = SANE_TYPE_FIXED;
596     po[OPT_BRX].unit = SANE_UNIT_MM;
597     po[OPT_BRX].size = sizeof (SANE_Word);
598     po[OPT_BRX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
599     po[OPT_BRX].constraint_type = SANE_CONSTRAINT_RANGE;
600     po[OPT_BRX].constraint.range = &(ps->pdev->x_range);
601     ps->brx = ps->pdev->x_range.max;
602 
603     po[OPT_BRY].name = SANE_NAME_SCAN_BR_Y;
604     po[OPT_BRY].title = SANE_TITLE_SCAN_BR_Y;
605     po[OPT_BRY].desc = SANE_DESC_SCAN_BR_Y;
606     po[OPT_BRY].type = SANE_TYPE_FIXED;
607     po[OPT_BRY].unit = SANE_UNIT_MM;
608     po[OPT_BRY].size = sizeof (SANE_Word);
609     po[OPT_BRY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
610     po[OPT_BRY].constraint_type = SANE_CONSTRAINT_RANGE;
611     po[OPT_BRY].constraint.range = &(ps->pdev->y_range);
612     ps->bry = ps->pdev->y_range.max;
613 
614     po[OPT_PREDEF_WINDOW].name = "predef-window";
615     po[OPT_PREDEF_WINDOW].title = SANE_I18N("Predefined settings");
616     po[OPT_PREDEF_WINDOW].desc = SANE_I18N(
617         "Provides standard scanning areas for photographs, printed pages "
618         "and the like.");
619     po[OPT_PREDEF_WINDOW].type = SANE_TYPE_STRING;
620     po[OPT_PREDEF_WINDOW].unit = SANE_UNIT_NONE;
621     po[OPT_PREDEF_WINDOW].size = 32;
622     po[OPT_PREDEF_WINDOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
623     {
624         static SANE_String_Const names[] =
625             {pdw_none, pdw_6X4, pdw_8X10, pdw_85X11, NULL};
626         po[OPT_PREDEF_WINDOW].constraint_type = SANE_CONSTRAINT_STRING_LIST;
627         po[OPT_PREDEF_WINDOW].constraint.string_list = names;
628     }
629     ps->predef_window = pdw_none;
630 
631     po[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement");
632     po[OPT_ENHANCEMENT_GROUP].desc = "";
633     po[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
634     po[OPT_ENHANCEMENT_GROUP].cap = 0;
635     po[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
636 
637     /* bit depth */
638     po[OPT_BIT_DEPTH].name  = SANE_NAME_BIT_DEPTH;
639     po[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
640     po[OPT_BIT_DEPTH].desc  = SANE_DESC_BIT_DEPTH;
641     po[OPT_BIT_DEPTH].type  = SANE_TYPE_INT;
642     po[OPT_BIT_DEPTH].unit  = SANE_UNIT_BIT;
643     po[OPT_BIT_DEPTH].size = sizeof (SANE_Word);
644     po[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
645     po[OPT_BIT_DEPTH].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
646     bit_depths = 0;
647     bit_depth_list[++bit_depths] = def_bpp;
648     switch (ps->pdev->model)
649     {
650     case PERFECTION2480:
651     case PERFECTION3490:
652         bit_depth_list[++bit_depths] = 16;
653         break;
654     case SCANWIT2720S:
655         bit_depth_list[bit_depths] = 12;
656         break;
657     default:
658         break;
659     }
660     bit_depth_list[0] = bit_depths;
661     po[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list;
662     if (ps->pdev->model == SCANWIT2720S)
663     {
664         ps->val[OPT_BIT_DEPTH].w = 12;
665         ps->bpp_scan = 12;
666     }
667     else
668     {
669         ps->val[OPT_BIT_DEPTH].w = def_bpp;
670         ps->bpp_scan = def_bpp;
671     }
672 
673     po[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL;
674     po[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL;
675     po[OPT_QUALITY_CAL].desc = SANE_DESC_QUALITY_CAL;
676     po[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL;
677     po[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE;
678     po[OPT_QUALITY_CAL].size = sizeof (SANE_Bool);
679     po[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE;
680     po[OPT_QUALITY_CAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
681     ps->val[OPT_QUALITY_CAL].b = DEFAULT_QUALITY;
682     /* Disable quality calibration option if not supported
683        Note: Snapscan e52 and Prisa5300 do not support quality calibration,
684        although HCFG_CAL_ALLOWED is set. */
685     if ((!(ps->hconfig & HCFG_CAL_ALLOWED))
686         || (ps->pdev->model == SNAPSCANE52)
687         || (ps->pdev->model == PERFECTION1670)
688         || (ps->pdev->model == PRISA5150)
689         || (ps->pdev->model == PRISA5300)) {
690         po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE;
691         ps->val[OPT_QUALITY_CAL].b = SANE_FALSE;
692     }
693 
694     if ((ps->pdev->model == PRISA5150) ||
695         (ps->pdev->model == STYLUS_CX1500))
696     {
697         po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE;
698         ps->val[OPT_QUALITY_CAL].b = SANE_TRUE;
699     }
700 
701     po[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND;
702     po[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND;
703     po[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND;
704     po[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL;
705     po[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE;
706     po[OPT_GAMMA_BIND].size = sizeof (SANE_Bool);
707     po[OPT_GAMMA_BIND].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
708     po[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE;
709     ps->val[OPT_GAMMA_BIND].b = DEFAULT_GAMMA_BIND;
710 
711     po[OPT_GAMMA_GS].name = SANE_NAME_ANALOG_GAMMA;
712     po[OPT_GAMMA_GS].title = SANE_TITLE_ANALOG_GAMMA;
713     po[OPT_GAMMA_GS].desc = SANE_DESC_ANALOG_GAMMA;
714     po[OPT_GAMMA_GS].type = SANE_TYPE_FIXED;
715     po[OPT_GAMMA_GS].unit = SANE_UNIT_NONE;
716     po[OPT_GAMMA_GS].size = sizeof (SANE_Word);
717     po[OPT_GAMMA_GS].cap =
718         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
719     po[OPT_GAMMA_GS].constraint_type = SANE_CONSTRAINT_RANGE;
720     po[OPT_GAMMA_GS].constraint.range = &gamma_range;
721     ps->gamma_gs = DEFAULT_GAMMA;
722 
723     po[OPT_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R;
724     po[OPT_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R;
725     po[OPT_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R;
726     po[OPT_GAMMA_R].type = SANE_TYPE_FIXED;
727     po[OPT_GAMMA_R].unit = SANE_UNIT_NONE;
728     po[OPT_GAMMA_R].size = sizeof (SANE_Word);
729     po[OPT_GAMMA_R].cap =
730         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
731     po[OPT_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE;
732     po[OPT_GAMMA_R].constraint.range = &gamma_range;
733     ps->gamma_r = DEFAULT_GAMMA;
734 
735     po[OPT_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G;
736     po[OPT_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G;
737     po[OPT_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G;
738     po[OPT_GAMMA_G].type = SANE_TYPE_FIXED;
739     po[OPT_GAMMA_G].unit = SANE_UNIT_NONE;
740     po[OPT_GAMMA_G].size = sizeof (SANE_Word);
741     po[OPT_GAMMA_G].cap =
742         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
743     po[OPT_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE;
744     po[OPT_GAMMA_G].constraint.range = &gamma_range;
745     ps->gamma_g = DEFAULT_GAMMA;
746 
747     po[OPT_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B;
748     po[OPT_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B;
749     po[OPT_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B;
750     po[OPT_GAMMA_B].type = SANE_TYPE_FIXED;
751     po[OPT_GAMMA_B].unit = SANE_UNIT_NONE;
752     po[OPT_GAMMA_B].size = sizeof (SANE_Word);
753     po[OPT_GAMMA_B].cap =
754         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
755     po[OPT_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE;
756     po[OPT_GAMMA_B].constraint.range = &gamma_range;
757     ps->gamma_b = DEFAULT_GAMMA;
758 
759     po[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
760     po[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
761     po[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
762     po[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
763     po[OPT_CUSTOM_GAMMA].unit = SANE_UNIT_NONE;
764     po[OPT_CUSTOM_GAMMA].size = sizeof (SANE_Bool);
765     po[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
766     ps->val[OPT_CUSTOM_GAMMA].b = DEFAULT_CUSTOM_GAMMA;
767 
768     po[OPT_GAMMA_VECTOR_GS].name = SANE_NAME_GAMMA_VECTOR;
769     po[OPT_GAMMA_VECTOR_GS].title = SANE_TITLE_GAMMA_VECTOR;
770     po[OPT_GAMMA_VECTOR_GS].desc = SANE_DESC_GAMMA_VECTOR;
771     po[OPT_GAMMA_VECTOR_GS].type = SANE_TYPE_INT;
772     po[OPT_GAMMA_VECTOR_GS].unit = SANE_UNIT_NONE;
773     po[OPT_GAMMA_VECTOR_GS].size = ps->gamma_length * sizeof (SANE_Word);
774     po[OPT_GAMMA_VECTOR_GS].cap =
775         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
776     po[OPT_GAMMA_VECTOR_GS].constraint_type = SANE_CONSTRAINT_RANGE;
777     po[OPT_GAMMA_VECTOR_GS].constraint.range = &gamma_vrange;
778     ps->val[OPT_GAMMA_VECTOR_GS].wa = ps->gamma_table_gs;
779 
780     po[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
781     po[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
782     po[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
783     po[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
784     po[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
785     po[OPT_GAMMA_VECTOR_R].size = ps->gamma_length * sizeof (SANE_Word);
786     po[OPT_GAMMA_VECTOR_R].cap =
787         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
788     po[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
789     po[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_vrange;
790     ps->val[OPT_GAMMA_VECTOR_R].wa = ps->gamma_table_r;
791 
792     po[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
793     po[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
794     po[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
795     po[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
796     po[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
797     po[OPT_GAMMA_VECTOR_G].size = ps->gamma_length * sizeof (SANE_Word);
798     po[OPT_GAMMA_VECTOR_G].cap =
799         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
800     po[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
801     po[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_vrange;
802     ps->val[OPT_GAMMA_VECTOR_G].wa = ps->gamma_table_g;
803 
804     po[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
805     po[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
806     po[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
807     po[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
808     po[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
809     po[OPT_GAMMA_VECTOR_B].size = ps->gamma_length * sizeof (SANE_Word);
810     po[OPT_GAMMA_VECTOR_B].cap =
811         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
812     po[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
813     po[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_vrange;
814     ps->val[OPT_GAMMA_VECTOR_B].wa = ps->gamma_table_b;
815 
816     po[OPT_HALFTONE].name = SANE_NAME_HALFTONE;
817     po[OPT_HALFTONE].title = SANE_TITLE_HALFTONE;
818     po[OPT_HALFTONE].desc = SANE_DESC_HALFTONE;
819     po[OPT_HALFTONE].type = SANE_TYPE_BOOL;
820     po[OPT_HALFTONE].unit = SANE_UNIT_NONE;
821     po[OPT_HALFTONE].size = sizeof (SANE_Bool);
822     po[OPT_HALFTONE].cap =
823         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
824     po[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_NONE;
825     ps->halftone = DEFAULT_HALFTONE;
826 
827     po[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
828     po[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
829     po[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
830     po[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
831     po[OPT_HALFTONE_PATTERN].unit = SANE_UNIT_NONE;
832     po[OPT_HALFTONE_PATTERN].size = 32;
833     po[OPT_HALFTONE_PATTERN].cap =
834         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
835     po[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
836     switch (ps->hconfig & HCFG_HT)
837     {
838     case HCFG_HT:
839         /* both 16x16, 8x8 matrices */
840         {
841             static SANE_String_Const names[] = {dm_dd8x8, dm_dd16x16, NULL};
842 
843             po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
844             ps->dither_matrix = dm_dd8x8;
845         }
846         break;
847     case HCFG_HT16:
848         /* 16x16 matrices only */
849         {
850             static SANE_String_Const names[] = {dm_dd16x16, NULL};
851 
852             po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
853             ps->dither_matrix = dm_dd16x16;
854         }
855         break;
856     case HCFG_HT8:
857         /* 8x8 matrices only */
858         {
859             static SANE_String_Const names[] = {dm_dd8x8, NULL};
860 
861             po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
862             ps->dither_matrix = dm_dd8x8;
863         }
864         break;
865     default:
866         /* no halftone matrices */
867         {
868             static SANE_String_Const names[] = {dm_none, NULL};
869 
870             po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
871             ps->dither_matrix = dm_none;
872         }
873     }
874 
875     po[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
876     po[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
877     po[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
878     po[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
879     po[OPT_NEGATIVE].unit = SANE_UNIT_NONE;
880     po[OPT_NEGATIVE].size = sizeof (SANE_Bool);
881     po[OPT_NEGATIVE].cap =
882         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC;
883     po[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
884     ps->negative = DEFAULT_NEGATIVE;
885 
886     po[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
887     po[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
888     po[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
889     po[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
890     po[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
891     po[OPT_THRESHOLD].size = sizeof (SANE_Int);
892     po[OPT_THRESHOLD].cap =
893         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
894     po[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
895     po[OPT_THRESHOLD].constraint.range = &positive_percent_range;
896     ps->threshold = DEFAULT_THRESHOLD;
897 
898     po[OPT_FRAME_NO].name = SANE_I18N("Frame");
899     po[OPT_FRAME_NO].title = SANE_I18N("Frame to be scanned");
900     po[OPT_FRAME_NO].desc = frame_desc;
901     po[OPT_FRAME_NO].type = SANE_TYPE_INT;
902     po[OPT_FRAME_NO].unit = SANE_UNIT_NONE;
903     po[OPT_FRAME_NO].size = sizeof (SANE_Int);
904     po[OPT_FRAME_NO].cap = SANE_CAP_SOFT_SELECT
905                        | SANE_CAP_SOFT_DETECT
906                        | SANE_CAP_INACTIVE;
907     po[OPT_FRAME_NO].constraint_type = SANE_CONSTRAINT_RANGE;
908     po[OPT_FRAME_NO].constraint.range = &frame_range;
909     ps->frame_no = def_frame_no;
910 
911     po[OPT_FOCUS_MODE].name = SANE_I18N("Focus-mode");
912     po[OPT_FOCUS_MODE].title = SANE_I18N("Auto or manual focus");
913     po[OPT_FOCUS_MODE].desc = focus_mode_desc;
914     po[OPT_FOCUS_MODE].type = SANE_TYPE_STRING;
915     po[OPT_FOCUS_MODE].unit = SANE_UNIT_NONE;
916     po[OPT_FOCUS_MODE].size = 16;
917     po[OPT_FOCUS_MODE].cap = SANE_CAP_SOFT_SELECT
918                        | SANE_CAP_SOFT_DETECT
919                        | SANE_CAP_INACTIVE;
920     po[OPT_FOCUS_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
921     po[OPT_FOCUS_MODE].constraint.string_list = focus_modes;
922     ps->focus_mode_s= md_auto;
923     ps->focus_mode = MD_AUTO;
924 
925     po[OPT_FOCUS_POINT].name = SANE_I18N("Focus-point");
926     po[OPT_FOCUS_POINT].title = SANE_I18N("Focus point");
927     po[OPT_FOCUS_POINT].desc = focus_desc;
928     po[OPT_FOCUS_POINT].type = SANE_TYPE_INT;
929     po[OPT_FOCUS_POINT].unit = SANE_UNIT_NONE;
930     po[OPT_FOCUS_POINT].size = sizeof (SANE_Int);
931     po[OPT_FOCUS_POINT].cap = SANE_CAP_SOFT_SELECT
932                        | SANE_CAP_SOFT_DETECT
933                        | SANE_CAP_INACTIVE;
934     po[OPT_FOCUS_POINT].constraint_type = SANE_CONSTRAINT_RANGE;
935     po[OPT_FOCUS_POINT].constraint.range = &focus_range;
936 
937     po[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced");
938     po[OPT_ADVANCED_GROUP].desc = "";
939     po[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
940     po[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
941     po[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
942 
943     po[OPT_RGB_LPR].name = "rgb-lpr";
944     po[OPT_RGB_LPR].title = SANE_I18N("Color lines per read");
945     po[OPT_RGB_LPR].desc = lpr_desc;
946     po[OPT_RGB_LPR].type = SANE_TYPE_INT;
947     po[OPT_RGB_LPR].unit = SANE_UNIT_NONE;
948     po[OPT_RGB_LPR].size = sizeof (SANE_Word);
949     po[OPT_RGB_LPR].cap =
950         SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC;
951     po[OPT_RGB_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
952     po[OPT_RGB_LPR].constraint.range = &lpr_range;
953     ps->rgb_lpr = def_rgb_lpr;
954 
955     po[OPT_GS_LPR].name = "gs-lpr";
956     po[OPT_GS_LPR].title = SANE_I18N("Grayscale lines per read");
957     po[OPT_GS_LPR].desc = lpr_desc;
958     po[OPT_GS_LPR].type = SANE_TYPE_INT;
959     po[OPT_GS_LPR].unit = SANE_UNIT_NONE;
960     po[OPT_GS_LPR].size = sizeof (SANE_Word);
961     po[OPT_GS_LPR].cap = SANE_CAP_SOFT_SELECT
962                        | SANE_CAP_SOFT_DETECT
963                        | SANE_CAP_ADVANCED
964                        | SANE_CAP_INACTIVE
965                        | SANE_CAP_AUTOMATIC;
966     po[OPT_GS_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
967     po[OPT_GS_LPR].constraint.range = &lpr_range;
968     ps->gs_lpr = def_gs_lpr;
969     control_options(ps);
970 }
971 
sane_get_option_descriptor(SANE_Handle h,SANE_Int n)972 const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h,
973                                                           SANE_Int n)
974 {
975     DBG (DL_OPTION_TRACE,
976          "sane_snapscan_get_option_descriptor (%p, %ld)\n",
977          (void *) h,
978          (long) n);
979 
980     if ((n >= 0) && (n < NUM_OPTS))
981         return ((SnapScan_Scanner *) h)->options + n;
982     return NULL;
983 }
984 
985 /* Activates or deactivates options depending on mode  */
control_options(SnapScan_Scanner * pss)986 static void control_options(SnapScan_Scanner *pss)
987 {
988     /* first deactivate all options */
989     pss->options[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
990     pss->options[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
991     pss->options[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
992     pss->options[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE;
993     pss->options[OPT_GAMMA_GS].cap |= SANE_CAP_INACTIVE;
994     pss->options[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE;
995     pss->options[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE;
996     pss->options[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE;
997     pss->options[OPT_GAMMA_VECTOR_GS].cap |= SANE_CAP_INACTIVE;
998     pss->options[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
999     pss->options[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1000     pss->options[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1001     pss->options[OPT_BIT_DEPTH].cap  |= SANE_CAP_INACTIVE;
1002 
1003     if ((pss->mode == MD_COLOUR) ||
1004         ((pss->mode == MD_BILEVELCOLOUR) && (pss->hconfig & HCFG_HT) &&
1005          pss->halftone))
1006     {
1007         pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1008         pss->options[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE;
1009         if (pss->val[OPT_CUSTOM_GAMMA].b)
1010         {
1011             if (pss->val[OPT_GAMMA_BIND].b)
1012             {
1013                 pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
1014             }
1015             else
1016             {
1017                 pss->options[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
1018                 pss->options[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
1019                 pss->options[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
1020             }
1021         }
1022         else
1023         {
1024             pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1025             pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1026             if (pss->val[OPT_GAMMA_BIND].b)
1027             {
1028                 pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
1029             }
1030             else
1031             {
1032                 pss->options[OPT_GAMMA_R].cap &= ~SANE_CAP_INACTIVE;
1033                 pss->options[OPT_GAMMA_G].cap &= ~SANE_CAP_INACTIVE;
1034                 pss->options[OPT_GAMMA_B].cap &= ~SANE_CAP_INACTIVE;
1035             }
1036         }
1037     }
1038     else if ((pss->mode == MD_GREYSCALE) ||
1039              ((pss->mode == MD_LINEART) && (pss->hconfig & HCFG_HT) &&
1040               pss->halftone))
1041     {
1042         pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1043 
1044         if (pss->val[OPT_CUSTOM_GAMMA].b)
1045         {
1046             pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
1047         }
1048         else
1049         {
1050             pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
1051             pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
1052             pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
1053         }
1054     }
1055     if ((pss->mode == MD_GREYSCALE) || (pss->mode == MD_COLOUR))
1056     {
1057         switch(pss->pdev->model)
1058         {
1059         case PERFECTION2480:
1060         case PERFECTION3490:
1061             pss->options[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE;
1062             break;
1063         default:
1064             break;
1065         }
1066     }
1067     if (pss->pdev->model == SCANWIT2720S)
1068     {
1069         pss->options[OPT_FRAME_NO].cap &= ~SANE_CAP_INACTIVE;
1070         pss->options[OPT_FOCUS_MODE].cap &= ~SANE_CAP_INACTIVE;
1071         if (pss->focus_mode == MD_MANUAL)
1072         {
1073             pss->options[OPT_FOCUS_POINT].cap &= ~SANE_CAP_INACTIVE;
1074         }
1075     }
1076 }
1077 
sane_control_option(SANE_Handle h,SANE_Int n,SANE_Action a,void * v,SANE_Int * i)1078 SANE_Status sane_control_option (SANE_Handle h,
1079                                  SANE_Int n,
1080                                  SANE_Action a,
1081                                  void *v,
1082                                  SANE_Int *i)
1083 {
1084     static const char *me = "sane_snapscan_control_option";
1085     SnapScan_Scanner *pss = h;
1086     SnapScan_Device *pdev = pss->pdev;
1087     static SANE_Status status;
1088 
1089     DBG (DL_OPTION_TRACE,
1090         "%s (%p, %ld, %ld, %p, %p)\n",
1091         me,
1092         (void *) h,
1093         (long) n,
1094         (long) a,
1095         v,
1096         (void *) i);
1097 
1098     switch (a)
1099     {
1100     case SANE_ACTION_GET_VALUE:
1101         /* prevent getting of inactive options */
1102         if (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap)) {
1103             return SANE_STATUS_INVAL;
1104         }
1105         switch (n)
1106         {
1107         case OPT_COUNT:
1108             *(SANE_Int *) v = NUM_OPTS;
1109             break;
1110         case OPT_SCANRES:
1111             *(SANE_Int *) v = pss->res;
1112             break;
1113         case OPT_PREVIEW:
1114             *(SANE_Bool *) v = pss->preview;
1115             break;
1116         case OPT_HIGHQUALITY:
1117             *(SANE_Bool *) v = pss->highquality;
1118             break;
1119         case OPT_MODE:
1120             DBG (DL_VERBOSE,
1121                  "%s: writing \"%s\" to location %p\n",
1122                  me,
1123                  pss->mode_s,
1124                  (void *) v);
1125             strcpy ((SANE_String) v, pss->mode_s);
1126             break;
1127         case OPT_PREVIEW_MODE:
1128             DBG (DL_VERBOSE,
1129                  "%s: writing \"%s\" to location %p\n",
1130                  me,
1131                  pss->preview_mode_s,
1132                  (void *) v);
1133             strcpy ((SANE_String) v, pss->preview_mode_s);
1134             break;
1135         case OPT_SOURCE:
1136             strcpy (v, pss->source_s);
1137             break;
1138         case OPT_TLX:
1139             *(SANE_Fixed *) v = pss->tlx;
1140             break;
1141         case OPT_TLY:
1142             *(SANE_Fixed *) v = pss->tly;
1143             break;
1144         case OPT_BRX:
1145             *(SANE_Fixed *) v = pss->brx;
1146             break;
1147         case OPT_BRY:
1148             *(SANE_Fixed *) v = pss->bry;
1149             break;
1150         case OPT_BRIGHTNESS:
1151             *(SANE_Int *) v = pss->bright << SANE_FIXED_SCALE_SHIFT;
1152             break;
1153         case OPT_CONTRAST:
1154             *(SANE_Int *) v = pss->contrast << SANE_FIXED_SCALE_SHIFT;
1155             break;
1156         case OPT_PREDEF_WINDOW:
1157             DBG (DL_VERBOSE,
1158                 "%s: writing \"%s\" to location %p\n",
1159                 me,
1160                 pss->predef_window,
1161                 (void *) v);
1162             strcpy ((SANE_String) v, pss->predef_window);
1163             break;
1164         case OPT_GAMMA_GS:
1165             *(SANE_Fixed *) v = pss->gamma_gs;
1166             break;
1167         case OPT_GAMMA_R:
1168             *(SANE_Fixed *) v = pss->gamma_r;
1169             break;
1170         case OPT_GAMMA_G:
1171             *(SANE_Fixed *) v = pss->gamma_g;
1172             break;
1173         case OPT_GAMMA_B:
1174             *(SANE_Fixed *) v = pss->gamma_b;
1175             break;
1176         case OPT_CUSTOM_GAMMA:
1177         case OPT_GAMMA_BIND:
1178         case OPT_QUALITY_CAL:
1179             *(SANE_Bool *) v = pss->val[n].b;
1180             break;
1181 
1182         case OPT_GAMMA_VECTOR_GS:
1183         case OPT_GAMMA_VECTOR_R:
1184         case OPT_GAMMA_VECTOR_G:
1185         case OPT_GAMMA_VECTOR_B:
1186             memcpy (v, pss->val[n].wa, pss->options[n].size);
1187             break;
1188         case OPT_HALFTONE:
1189             *(SANE_Bool *) v = pss->halftone;
1190             break;
1191         case OPT_HALFTONE_PATTERN:
1192             DBG (DL_VERBOSE,
1193                 "%s: writing \"%s\" to location %p\n",
1194                 me,
1195                 pss->dither_matrix,
1196                 (void *) v);
1197             strcpy ((SANE_String) v, pss->dither_matrix);
1198             break;
1199         case OPT_NEGATIVE:
1200             *(SANE_Bool *) v = pss->negative;
1201             break;
1202         case OPT_THRESHOLD:
1203             *(SANE_Int *) v = pss->threshold << SANE_FIXED_SCALE_SHIFT;
1204             break;
1205         case OPT_RGB_LPR:
1206             *(SANE_Int *) v = pss->rgb_lpr;
1207             break;
1208         case OPT_GS_LPR:
1209             *(SANE_Int *) v = pss->gs_lpr;
1210             break;
1211         case OPT_BIT_DEPTH:
1212             *(SANE_Int *) v = pss->val[OPT_BIT_DEPTH].w;
1213             break;
1214         case OPT_FRAME_NO:
1215             *(SANE_Int *) v = pss->frame_no;
1216             break;
1217         case OPT_FOCUS_MODE:
1218             strcpy ((SANE_String) v, pss->focus_mode_s);
1219             break;
1220         case OPT_FOCUS_POINT:
1221             *(SANE_Int *) v = pss->focus;
1222             break;
1223         default:
1224             DBG (DL_MAJOR_ERROR,
1225                  "%s: invalid option number %ld\n",
1226                  me,
1227                  (long) n);
1228             return SANE_STATUS_UNSUPPORTED;
1229         }
1230         break;
1231     case SANE_ACTION_SET_VALUE:
1232         if (i)
1233             *i = 0;
1234         /* prevent setting of inactive options */
1235         if ((!SANE_OPTION_IS_SETTABLE(pss->options[n].cap)) ||
1236             (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap))) {
1237             return SANE_STATUS_INVAL;
1238         }
1239         /* prevent setting of options during a scan */
1240         if ((pss->state==ST_SCAN_INIT) || (pss->state==ST_SCANNING)) {
1241             DBG(DL_INFO,
1242                 "set value for option %s ignored: scanner is still scanning (status %d)\n",
1243                 pss->options[n].name,
1244                 pss->state
1245             );
1246             return SANE_STATUS_DEVICE_BUSY;
1247         }
1248         status = sanei_constrain_value(&pss->options[n], v, i);
1249         if (status != SANE_STATUS_GOOD) {
1250             return status;
1251         }
1252         switch (n)
1253         {
1254         case OPT_COUNT:
1255             return SANE_STATUS_UNSUPPORTED;
1256         case OPT_SCANRES:
1257             pss->res = *(SANE_Int *) v;
1258             if (i)
1259                 *i |= SANE_INFO_RELOAD_PARAMS;
1260             break;
1261         case OPT_PREVIEW:
1262             pss->preview = *(SANE_Bool *) v;
1263             if (i)
1264                 *i |= SANE_INFO_RELOAD_PARAMS;
1265             break;
1266         case OPT_HIGHQUALITY:
1267             pss->highquality = *(SANE_Bool *) v;
1268             if (i)
1269                 *i |= SANE_INFO_RELOAD_PARAMS;
1270             break;
1271         case OPT_MODE:
1272             {
1273                 char *s = (SANE_String) v;
1274                 if (strcmp (s, md_colour) == 0)
1275                 {
1276                     pss->mode_s = md_colour;
1277                     pss->mode = MD_COLOUR;
1278                     if (pss->preview_mode_s == md_auto)
1279                       pss->preview_mode = MD_COLOUR;
1280                     pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
1281                     pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1282                     pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
1283                     pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1284                     pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
1285                     pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
1286                 }
1287                 else if (strcmp (s, md_bilevelcolour) == 0)
1288                 {
1289                     int ht_cap = pss->hconfig & HCFG_HT;
1290                     pss->mode_s = md_bilevelcolour;
1291                     pss->mode = MD_BILEVELCOLOUR;
1292                     if (pss->preview_mode_s == md_auto)
1293                       pss->preview_mode = MD_BILEVELCOLOUR;
1294                     if (ht_cap)
1295                         pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
1296                     if (ht_cap && pss->halftone)
1297                     {
1298                         pss->options[OPT_HALFTONE_PATTERN].cap &=
1299                             ~SANE_CAP_INACTIVE;
1300                     }
1301                     else
1302                     {
1303                         pss->options[OPT_HALFTONE_PATTERN].cap |=
1304                             SANE_CAP_INACTIVE;
1305                     }
1306                     pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
1307                     pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1308                     pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
1309                     pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
1310                 }
1311                 else if (strcmp (s, md_greyscale) == 0)
1312                 {
1313                     pss->mode_s = md_greyscale;
1314                     pss->mode = MD_GREYSCALE;
1315                     if (pss->preview_mode_s == md_auto)
1316                       pss->preview_mode = MD_GREYSCALE;
1317                     pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
1318                     pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1319                     pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
1320                     pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1321                     pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
1322                     pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
1323                 }
1324                 else if (strcmp (s, md_lineart) == 0)
1325                 {
1326                     int ht_cap = pss->hconfig & HCFG_HT;
1327                     pss->mode_s = md_lineart;
1328                     pss->mode = MD_LINEART;
1329                     if (pss->preview_mode_s == md_auto)
1330                       pss->preview_mode = MD_LINEART;
1331                     if (ht_cap)
1332                         pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
1333                     if (ht_cap && pss->halftone)
1334                     {
1335                         pss->options[OPT_HALFTONE_PATTERN].cap &=
1336                             ~SANE_CAP_INACTIVE;
1337                         pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1338                     }
1339                     else
1340                     {
1341                         pss->options[OPT_HALFTONE_PATTERN].cap |=
1342                             SANE_CAP_INACTIVE;
1343                         pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
1344                     }
1345                     pss->options[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE;
1346                     pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
1347                     pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
1348                 }
1349                 else
1350                 {
1351                     DBG (DL_MAJOR_ERROR,
1352                         "%s: internal error: given illegal mode "
1353                         "string \"%s\"\n",
1354                         me,
1355                         s);
1356                 }
1357             }
1358             control_options (pss);
1359             if (i)
1360                 *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1361             break;
1362         case OPT_PREVIEW_MODE:
1363             {
1364                 char *s = (SANE_String) v;
1365                 if (strcmp (s, md_auto) == 0)
1366                 {
1367                   pss->preview_mode_s = md_auto;
1368                   pss->preview_mode = pss->mode;
1369                 }
1370                 else if (strcmp (s, md_colour) == 0)
1371                 {
1372                     pss->preview_mode_s = md_colour;
1373                     pss->preview_mode = MD_COLOUR;
1374                 }
1375                 else if (strcmp (s, md_bilevelcolour) == 0)
1376                 {
1377                     pss->preview_mode_s = md_bilevelcolour;
1378                     pss->preview_mode = MD_BILEVELCOLOUR;
1379                 }
1380                 else if (strcmp (s, md_greyscale) == 0)
1381                 {
1382                     pss->preview_mode_s = md_greyscale;
1383                     pss->preview_mode = MD_GREYSCALE;
1384                 }
1385                 else if (strcmp (s, md_lineart) == 0)
1386                 {
1387                     pss->preview_mode_s = md_lineart;
1388                     pss->preview_mode = MD_LINEART;
1389                 }
1390                 else
1391                 {
1392                     DBG (DL_MAJOR_ERROR,
1393                         "%s: internal error: given illegal mode string "
1394                         "\"%s\"\n",
1395                         me,
1396                         s);
1397                 }
1398                 break;
1399             }
1400         case OPT_SOURCE:
1401             if (strcmp(v, src_flatbed) == 0)
1402             {
1403                 pss->source = SRC_FLATBED;
1404                 pss->pdev->x_range.max = x_range_fb.max;
1405                 pss->pdev->y_range.max = y_range_fb.max;
1406             }
1407             else if (strcmp(v, src_tpo) == 0)
1408             {
1409                 pss->source = SRC_TPO;
1410                 pss->pdev->x_range.max = x_range_tpo.max;
1411                 pss->pdev->y_range.max = y_range_tpo.max;
1412             }
1413             else if (strcmp(v, src_adf) == 0)
1414             {
1415                 pss->source = SRC_ADF;
1416                 pss->pdev->x_range.max = x_range_fb.max;
1417                 pss->pdev->y_range.max = y_range_fb.max;
1418             }
1419             else
1420             {
1421                 DBG (DL_MAJOR_ERROR,
1422                      "%s: internal error: given illegal source string "
1423                       "\"%s\"\n",
1424                      me,
1425                      (char *) v);
1426             }
1427             /* Adjust actual range values to new max values */
1428             if (pss->brx > pss->pdev->x_range.max)
1429                 pss->brx = pss->pdev->x_range.max;
1430             if (pss->bry > pss->pdev->y_range.max)
1431                 pss->bry = pss->pdev->y_range.max;
1432             pss->predef_window = pdw_none;
1433             if (pss->source_s)
1434                 free (pss->source_s);
1435             pss->source_s = (SANE_Char *) strdup(v);
1436             if (i)
1437                 *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1438             break;
1439         case OPT_TLX:
1440             pss->tlx = *(SANE_Fixed *) v;
1441             pss->predef_window = pdw_none;
1442             if (pss->tlx > pdev->x_range.max) {
1443                 pss->tlx = pdev->x_range.max;
1444             }
1445             if (pss->brx < pss->tlx) {
1446                 pss->brx = pss->tlx;
1447             }
1448             if (i)
1449                 *i |= SANE_INFO_RELOAD_PARAMS;
1450             break;
1451         case OPT_TLY:
1452             pss->tly = *(SANE_Fixed *) v;
1453             pss->predef_window = pdw_none;
1454             if (pss->tly > pdev->y_range.max){
1455                 pss->tly = pdev->y_range.max;
1456             }
1457             if (pss->bry < pss->tly) {
1458                 pss->bry = pss->tly;
1459             }
1460             if (i)
1461                 *i |= SANE_INFO_RELOAD_PARAMS;
1462             break;
1463         case OPT_BRX:
1464             pss->brx = *(SANE_Fixed *) v;
1465             pss->predef_window = pdw_none;
1466             if (pss->brx < pdev->x_range.min) {
1467                 pss->brx = pdev->x_range.min;
1468             }
1469             if (pss->brx < pss->tlx) {
1470                 pss->tlx = pss->brx;
1471             }
1472             if (i)
1473                 *i |= SANE_INFO_RELOAD_PARAMS;
1474             break;
1475         case OPT_BRY:
1476             pss->bry = *(SANE_Fixed *) v;
1477             pss->predef_window = pdw_none;
1478             if (pss->bry < pdev->y_range.min) {
1479                 pss->bry = pdev->y_range.min;
1480             }
1481             if (pss->bry < pss->tly) {
1482                 pss->tly = pss->bry;
1483             }
1484             if (i)
1485                 *i |= SANE_INFO_RELOAD_PARAMS;
1486             break;
1487         case OPT_BRIGHTNESS:
1488             pss->bright = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
1489             break;
1490         case OPT_CONTRAST:
1491             pss->contrast = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
1492             break;
1493         case OPT_PREDEF_WINDOW:
1494             {
1495                 char *s = (SANE_String) v;
1496                 if (strcmp (s, pdw_none) != 0)
1497                 {
1498                     pss->tlx = 0;
1499                     pss->tly = 0;
1500 
1501                     if (strcmp (s, pdw_6X4) == 0)
1502                     {
1503                         pss->predef_window = pdw_6X4;
1504                         pss->brx = SANE_FIX (6.0*MM_PER_IN);
1505                         pss->bry = SANE_FIX (4.0*MM_PER_IN);
1506                     }
1507                     else if (strcmp (s, pdw_8X10) == 0)
1508                     {
1509                         pss->predef_window = pdw_8X10;
1510                         pss->brx = SANE_FIX (8.0*MM_PER_IN);
1511                         pss->bry = SANE_FIX (10.0*MM_PER_IN);
1512                     }
1513                     else if (strcmp (s, pdw_85X11) == 0)
1514                     {
1515                         pss->predef_window = pdw_85X11;
1516                         pss->brx = SANE_FIX (8.5*MM_PER_IN);
1517                         pss->bry = SANE_FIX (11.0*MM_PER_IN);
1518                     }
1519                     else
1520                     {
1521                         DBG (DL_MAJOR_ERROR,
1522                              "%s: trying to set predef window with "
1523                              "garbage value.", me);
1524                         pss->predef_window = pdw_none;
1525                         pss->brx = SANE_FIX (6.0*MM_PER_IN);
1526                         pss->bry = SANE_FIX (4.0*MM_PER_IN);
1527                     }
1528                 }
1529                 else
1530                 {
1531                     pss->predef_window = pdw_none;
1532                 }
1533             }
1534             if (i)
1535                 *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1536             break;
1537         case OPT_GAMMA_GS:
1538             pss->gamma_gs = *(SANE_Fixed *) v;
1539             break;
1540         case OPT_GAMMA_R:
1541             pss->gamma_r = *(SANE_Fixed *) v;
1542             break;
1543         case OPT_GAMMA_G:
1544             pss->gamma_g = *(SANE_Fixed *) v;
1545             break;
1546         case OPT_GAMMA_B:
1547             pss->gamma_b = *(SANE_Fixed *) v;
1548             break;
1549         case OPT_QUALITY_CAL:
1550             pss->val[n].b = *(SANE_Bool *)v;
1551             break;
1552 
1553         case OPT_CUSTOM_GAMMA:
1554         case OPT_GAMMA_BIND:
1555         {
1556             SANE_Bool b = *(SANE_Bool *) v;
1557             if (b == pss->val[n].b) { break; }
1558             pss->val[n].b = b;
1559             control_options (pss);
1560             if (i)
1561             {
1562                 *i |= SANE_INFO_RELOAD_OPTIONS;
1563             }
1564             break;
1565         }
1566 
1567         case OPT_GAMMA_VECTOR_GS:
1568         case OPT_GAMMA_VECTOR_R:
1569         case OPT_GAMMA_VECTOR_G:
1570         case OPT_GAMMA_VECTOR_B:
1571             memcpy(pss->val[n].wa, v, pss->options[n].size);
1572             break;
1573         case OPT_HALFTONE:
1574             pss->halftone = *(SANE_Bool *) v;
1575             if (pss->halftone)
1576             {
1577                 switch (pss->mode)
1578                 {
1579                 case MD_BILEVELCOLOUR:
1580                     break;
1581                 case MD_LINEART:
1582                     pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1583                     break;
1584                 default:
1585                     break;
1586                 }
1587                 pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
1588             }
1589             else
1590             {
1591                 pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1592                 if (pss->mode == MD_LINEART)
1593                     pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
1594             }
1595             control_options (pss);
1596             if (i)
1597                 *i = SANE_INFO_RELOAD_OPTIONS;
1598             break;
1599         case OPT_HALFTONE_PATTERN:
1600             {
1601                 char *s = (SANE_String) v;
1602                 if (strcmp (s, dm_dd8x8) == 0)
1603                 {
1604                     pss->dither_matrix = dm_dd8x8;
1605                 }
1606                 else if (strcmp (s, dm_dd16x16) == 0)
1607                 {
1608                     pss->dither_matrix = dm_dd16x16;
1609                 }
1610                 else
1611                 {
1612                     DBG (DL_MAJOR_ERROR,
1613                          "%s: internal error: given illegal halftone pattern "
1614                          "string \"%s\"\n",
1615                          me,
1616                          s);
1617                 }
1618             }
1619             break;
1620         case OPT_NEGATIVE:
1621             pss->negative = *(SANE_Bool *) v;
1622             break;
1623         case OPT_THRESHOLD:
1624             pss->threshold = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
1625             break;
1626         case OPT_RGB_LPR:
1627             pss->rgb_lpr = *(SANE_Int *) v;
1628             break;
1629         case OPT_GS_LPR:
1630             pss->gs_lpr = *(SANE_Int *) v;
1631             break;
1632         case OPT_BIT_DEPTH:
1633             pss->val[OPT_BIT_DEPTH].w = *(SANE_Int *) v;
1634             if (i)
1635                 *i |= SANE_INFO_RELOAD_PARAMS;
1636             break;
1637         case OPT_FRAME_NO:
1638             pss->frame_no = *(SANE_Int *) v;
1639             break;
1640         case OPT_FOCUS_MODE:
1641             {
1642                 char *s = (SANE_String) v;
1643                 if (strcmp (s, md_manual) == 0)
1644                 {
1645                     pss->focus_mode_s = md_manual;
1646                     pss->focus_mode = MD_MANUAL;
1647                     pss->options[OPT_FOCUS_POINT].cap &= ~SANE_CAP_INACTIVE;
1648                 }
1649                 else
1650                 {
1651                     pss->focus_mode_s = md_auto;
1652                     pss->focus_mode = MD_AUTO;
1653                     pss->options[OPT_FOCUS_POINT].cap |= SANE_CAP_INACTIVE;
1654                 }
1655                 if (i)
1656                     *i = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1657                 break;
1658             }
1659         case OPT_FOCUS_POINT:
1660             pss->focus = *(SANE_Int *) v;
1661             break;
1662         default:
1663             DBG (DL_MAJOR_ERROR,
1664                  "%s: invalid option number %ld\n",
1665                  me,
1666                  (long) n);
1667             return SANE_STATUS_UNSUPPORTED;
1668         }
1669         DBG (DL_OPTION_TRACE, "%s: option %s set to value ",
1670              me, pss->options[n].name);
1671         switch (pss->options[n].type)
1672         {
1673         case SANE_TYPE_INT:
1674             DBG (DL_OPTION_TRACE, "%ld\n", (long) (*(SANE_Int *) v));
1675             break;
1676         case SANE_TYPE_BOOL:
1677             {
1678                 char *valstr = (*(SANE_Bool *) v == SANE_TRUE)  ?  "TRUE"  :  "FALSE";
1679                 DBG (DL_OPTION_TRACE, "%s\n", valstr);
1680             }
1681             break;
1682         default:
1683             DBG (DL_OPTION_TRACE, "other than an integer or boolean.\n");
1684             break;
1685         }
1686         break;
1687     case SANE_ACTION_SET_AUTO:
1688         if (i)
1689             *i = 0;
1690         switch (n)
1691         {
1692         case OPT_SCANRES:
1693             if (pss->pdev->model == SCANWIT2720S)
1694             {
1695                 pss->res = 1350;
1696             }
1697             else
1698             {
1699                 pss->res = 300;
1700             }
1701             if (i)
1702                 *i |= SANE_INFO_RELOAD_PARAMS;
1703             break;
1704         case OPT_PREVIEW:
1705             pss->preview = SANE_FALSE;
1706             if (i)
1707                 *i |= SANE_INFO_RELOAD_PARAMS;
1708             break;
1709         case OPT_HIGHQUALITY:
1710             pss->highquality = SANE_FALSE;
1711             if (i)
1712                 *i |= SANE_INFO_RELOAD_PARAMS;
1713             break;
1714         case OPT_MODE:
1715             pss->mode_s = md_colour;
1716             pss->mode = MD_COLOUR;
1717             pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
1718             pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1719             pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
1720             pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1721             pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
1722             pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
1723             control_options (pss);
1724             if (i)
1725                 *i = SANE_INFO_RELOAD_OPTIONS;
1726             break;
1727         case OPT_PREVIEW_MODE:
1728             pss->preview_mode_s = md_greyscale;
1729             pss->preview_mode = MD_GREYSCALE;
1730             break;
1731         case OPT_SOURCE:
1732             if (pss->pdev->model == SCANWIT2720S)
1733             {
1734                 pss->source = SRC_TPO;
1735                 pss->pdev->x_range.max = x_range_tpo.max;
1736                 pss->pdev->y_range.max = y_range_tpo.max;
1737                 pss->predef_window = pdw_none;
1738                 if (pss->source_s)
1739                     free (pss->source_s);
1740                 pss->source_s = (SANE_Char *) strdup(src_tpo);
1741             }
1742             else
1743             {
1744                 pss->source = SRC_FLATBED;
1745                 pss->pdev->x_range.max = x_range_fb.max;
1746                 pss->pdev->y_range.max = y_range_fb.max;
1747                 pss->predef_window = pdw_none;
1748                 if (pss->source_s)
1749                     free (pss->source_s);
1750                 pss->source_s = (SANE_Char *) strdup(src_flatbed);
1751             }
1752             if (i)
1753                 *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1754             break;
1755         case OPT_TLX:
1756             pss->tlx = pss->pdev->x_range.min;
1757             if (i)
1758                 *i |= SANE_INFO_RELOAD_PARAMS;
1759             break;
1760         case OPT_TLY:
1761             pss->tly = pss->pdev->y_range.min;
1762             if (i)
1763                 *i |= SANE_INFO_RELOAD_PARAMS;
1764             break;
1765         case OPT_BRX:
1766             pss->brx = pss->pdev->x_range.max;
1767             if (i)
1768                 *i |= SANE_INFO_RELOAD_PARAMS;
1769             break;
1770         case OPT_BRY:
1771             pss->bry = pss->pdev->y_range.max;
1772             if (i)
1773                 *i |= SANE_INFO_RELOAD_PARAMS;
1774             break;
1775         case OPT_NEGATIVE:
1776             pss->negative = DEFAULT_NEGATIVE;
1777             break;
1778         case OPT_RGB_LPR:
1779             pss->rgb_lpr = def_rgb_lpr;
1780             break;
1781         case OPT_GS_LPR:
1782             pss->gs_lpr = def_gs_lpr;
1783             break;
1784         case OPT_BIT_DEPTH:
1785             if (pss->pdev->model == SCANWIT2720S)
1786             {
1787                 pss->val[OPT_BIT_DEPTH].w = 12;
1788             }
1789             else
1790             {
1791                 pss->val[OPT_BIT_DEPTH].w = def_bpp;
1792             }
1793             break;
1794         case OPT_FRAME_NO:
1795             pss->frame_no = def_frame_no;
1796             break;
1797         case OPT_FOCUS_MODE:
1798             pss->focus_mode_s = md_auto;
1799             pss->focus_mode = MD_AUTO;
1800             if (i)
1801                 *i = SANE_INFO_RELOAD_OPTIONS;
1802             break;
1803         case OPT_FOCUS_POINT:
1804             pss->focus = 0x13e;
1805             break;
1806         default:
1807             DBG (DL_MAJOR_ERROR,
1808                  "%s: invalid option number %ld\n",
1809                  me,
1810                  (long) n);
1811             return SANE_STATUS_UNSUPPORTED;
1812         }
1813         break;
1814     default:
1815         DBG (DL_MAJOR_ERROR, "%s: invalid action code %ld\n", me, (long) a);
1816         return SANE_STATUS_UNSUPPORTED;
1817     }
1818     return SANE_STATUS_GOOD;
1819 }
1820 
1821 /*
1822  * Revision 1.35  2006/01/06 20:59:17  oliver-guest
1823  * Some fixes for the Epson Stylus CX 1500
1824  *
1825  * Revision 1.34  2006/01/01 22:57:01  oliver-guest
1826  * Added calibration data for Benq 5150 / 5250, preliminary support for Epson Stylus CX 1500
1827  *
1828  * Revision 1.33  2005/12/04 15:03:00  oliver-guest
1829  * Some fixes for Benq 5150
1830  *
1831  * Revision 1.32  2005/11/23 20:57:01  oliver-guest
1832  * Disable bilevel colour / halftoning for Epson 3490
1833  *
1834  * Revision 1.31  2005/11/17 23:47:10  oliver-guest
1835  * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead
1836  *
1837  * Revision 1.30  2005/11/15 20:11:18  oliver-guest
1838  * Enabled quality calibration for the Epson 3490
1839  *
1840  * Revision 1.29  2005/10/31 21:08:47  oliver-guest
1841  * Distinguish between Benq 5000/5000E/5000U
1842  *
1843  * Revision 1.28  2005/10/24 19:46:40  oliver-guest
1844  * Preview and range fix for Epson 2480/2580
1845  *
1846  * Revision 1.27  2005/10/13 22:43:30  oliver-guest
1847  * Fixes for 16 bit scan mode from Simon Munton
1848  *
1849  * Revision 1.26  2005/10/11 18:47:07  oliver-guest
1850  * Fixes for Epson 3490 and 16 bit scan mode
1851  *
1852  * Revision 1.25  2005/09/28 22:09:26  oliver-guest
1853  * Re-enabled enhanced inquiry command for Epson scanners (duh\!)
1854  *
1855  * Revision 1.24  2005/09/28 21:33:10  oliver-guest
1856  * Added 16 bit option for Epson scanners (untested)
1857  *
1858  * Revision 1.23  2005/08/16 20:15:10  oliver-guest
1859  * Removed C++-style comment
1860  *
1861  * Revision 1.22  2005/08/15 18:06:37  oliver-guest
1862  * Added support for Epson 3490/3590 (thanks to Matt Judge)
1863  *
1864  * Revision 1.21  2005/07/20 21:37:29  oliver-guest
1865  * Changed TPO scanning area for 2480/2580, re-enabled 2400 DPI for 2480/2580
1866  *
1867  * Revision 1.20  2005/05/22 11:50:24  oliver-guest
1868  * Disabled 2400 DPI for Epson 2480
1869  *
1870  * Revision 1.19  2004/12/09 23:21:47  oliver-guest
1871  * Added quality calibration for Epson 2480 (by Simon Munton)
1872  *
1873  * Revision 1.18  2004/12/01 22:12:02  oliver-guest
1874  * Added support for Epson 1270
1875  *
1876  * Revision 1.17  2004/09/02 20:59:11  oliver-guest
1877  * Added support for Epson 2480
1878  *
1879  * Revision 1.16  2004/04/08 21:53:10  oliver-guest
1880  * Use sanei_thread in snapscan backend
1881  *
1882  * Revision 1.15  2004/04/02 20:19:23  oliver-guest
1883  * Various bugfixes for gamma correction (thanks to Robert Tsien)
1884  *
1885  * Revision 1.14  2004/02/01 13:32:26  oliver-guest
1886  * Fixed resolutions for Epson 1670
1887  *
1888  * Revision 1.13  2003/11/28 23:23:18  oliver-guest
1889  * Correct length of wordlist for resolutions_1600
1890  *
1891  * Revision 1.12  2003/11/09 21:43:45  oliver-guest
1892  * Disabled quality calibration for Epson Perfection 1670
1893  *
1894  * Revision 1.11  2003/11/08 09:50:27  oliver-guest
1895  * Fix TPO scanning range for Epson 1670
1896  *
1897  * Revision 1.10  2003/10/21 20:43:25  oliver-guest
1898  * Bugfixes for SnapScan backend
1899  *
1900  * Revision 1.9  2003/10/07 18:29:20  oliver-guest
1901  * Initial support for Epson 1670, minor bugfix
1902  *
1903  * Revision 1.8  2003/08/19 21:05:08  oliverschwartz
1904  * Scanner ID cleanup
1905  *
1906  * Revision 1.7  2003/04/30 20:49:39  oliverschwartz
1907  * SnapScan backend 1.4.26
1908  *
1909  * Revision 1.8  2003/04/30 20:42:18  oliverschwartz
1910  * Added support for Agfa Arcus 1200 (supplied by Valtteri Vuorikoski)
1911  *
1912  * Revision 1.7  2003/04/02 21:17:12  oliverschwartz
1913  * Fix for 1200 DPI with Acer 5000
1914  *
1915  * Revision 1.6  2002/07/12 23:23:06  oliverschwartz
1916  * Disable quality calibration for 5300
1917  *
1918  * Revision 1.5  2002/06/06 20:40:00  oliverschwartz
1919  * Changed default scan area for transparency unit of SnapScan e50
1920  *
1921  * Revision 1.4  2002/05/02 18:28:44  oliverschwartz
1922  * Added ADF support
1923  *
1924  * Revision 1.3  2002/04/27 14:43:59  oliverschwartz
1925  * - Remove SCSI debug options
1926  * - Fix option handling (errors detected by tstbackend)
1927  *
1928  * Revision 1.2  2002/04/23 22:50:24  oliverschwartz
1929  * Improve handling of scan area options
1930  *
1931  * Revision 1.1  2002/03/24 12:07:15  oliverschwartz
1932  * Moved option functions from snapscan.c to snapscan-options.c
1933  *
1934  *
1935  * */
1936