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