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