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