1 /*
2 Copyright (C) 2009, Panasonic Russia Ltd.
3 Copyright (C) 2010,2011, m. allan noah
4 */
5 /*
6 Panasonic KV-S40xx USB-SCSI scanner driver.
7 */
8
9 #include "../include/sane/config.h"
10
11 #include <string.h>
12 #define DEBUG_DECLARE_ONLY
13 #define BACKEND_NAME kvs40xx
14
15 #include "../include/sane/sanei_backend.h"
16 #include "../include/sane/saneopts.h"
17 #include "../include/sane/sanei.h"
18 #include "../include/sane/sanei_config.h"
19 #include "lassert.h"
20
21 #include "kvs40xx.h"
22
23 #include "../include/sane/sanei_debug.h"
24
25 #include <stdlib.h>
26
27 static inline unsigned
mm2scanner_units(unsigned mm)28 mm2scanner_units (unsigned mm)
29 {
30 return (mm * 12000 / 254.0 + .5);
31 }
32 struct restriction
33 {
34 unsigned ux, uy, ux_pix, uy_pix;
35 };
36
37 static struct restriction flatbad = { 14064, 20400, 7031, 63999 };
38 static struct restriction cw = { 14268, 128000, 7133, 63999 };
39 static struct restriction cl = { 10724, 128000, 5361, 63999 };
40
41 static inline int
check_area(struct scanner * s,unsigned ux,unsigned uy,unsigned bx,unsigned by)42 check_area (struct scanner *s, unsigned ux,
43 unsigned uy, unsigned bx, unsigned by)
44 {
45 int fb = !strcmp (s->val[SOURCE].s, SANE_I18N ("fb"));
46 struct restriction *r = fb ? &flatbad
47 : (s->id == KV_S4085CL || s->id == KV_S4065CL) ? &cl : &cw;
48 unsigned res = s->val[RESOLUTION].w;
49 unsigned w = bx - ux;
50 unsigned h = by - uy;
51 unsigned c1 = mm2scanner_units (ux + w);
52 unsigned c2 = mm2scanner_units (uy + h);
53 int c = c1 <= r->ux && c1 >= 16 && c2 >= 1 && c2 <= r->uy ? 0 : -1;
54 if (c)
55 return c;
56 if (mm2scanner_units (ux) > r->ux)
57 return -1;
58 if (res * mm2scanner_units (ux) / 1200 > r->ux_pix)
59 return -1;
60
61 if (res * mm2scanner_units (uy) / 1200 > r->uy_pix)
62 return -1;
63 return 0;
64 }
65
66 static size_t
max_string_size(const SANE_String_Const strings[])67 max_string_size (const SANE_String_Const strings[])
68 {
69 size_t size, max_size = 0;
70 SANE_Int i;
71
72 for (i = 0; strings[i]; ++i)
73 {
74 size = strlen (strings[i]) + 1;
75 if (size > max_size)
76 max_size = size;
77 }
78 return max_size;
79 }
80
81 static SANE_String_Const mode_list[] = {
82 SANE_VALUE_SCAN_MODE_LINEART,
83 SANE_VALUE_SCAN_MODE_GRAY,
84 SANE_VALUE_SCAN_MODE_COLOR,
85 NULL
86 };
87 static const unsigned mode_val[] = { 0, 2, 5 };
88 static const unsigned bps_val[] = { 1, 8, 24 };
89
90 static const SANE_Range resolutions_range = {
91 100,600,1
92 };
93
94 /* List of feeder modes */
95 static SANE_String_Const feeder_mode_list[] = {
96 SANE_I18N ("single"),
97 SANE_I18N ("continuous"),
98 NULL
99 };
100
101 /* List of scan sources */
102 static SANE_String_Const source_list[] = {
103 SANE_I18N ("adf"),
104 SANE_I18N ("fb"),
105 NULL
106 };
107
108 /* List of manual feed mode */
109 static SANE_String_Const manual_feed_list[] = {
110 SANE_I18N ("off"),
111 SANE_I18N ("wait_doc"),
112 SANE_I18N ("wait_doc_hopper_up"),
113 SANE_I18N ("wait_key"),
114 NULL
115 };
116
117 /* List of paper sizes */
118 static SANE_String_Const paper_list[] = {
119 SANE_I18N ("user_def"),
120 SANE_I18N ("business_card"),
121 SANE_I18N ("Check"),
122 SANE_I18N ("A3"),
123 SANE_I18N ("A4"),
124 SANE_I18N ("A5"),
125 SANE_I18N ("A6"),
126 SANE_I18N ("Letter"),
127 SANE_I18N ("Double letter 11x17 in"),
128 SANE_I18N ("B4"),
129 SANE_I18N ("B5"),
130 SANE_I18N ("B6"),
131 SANE_I18N ("Legal"),
132 NULL
133 };
134
135 static SANE_String_Const paper_list_woA3[] = {
136 SANE_I18N ("user_def"),
137 SANE_I18N ("business_card"),
138 SANE_I18N ("Check"),
139 /*SANE_I18N ("A3"), */
140 SANE_I18N ("A4"),
141 SANE_I18N ("A5"),
142 SANE_I18N ("A6"),
143 SANE_I18N ("Letter"),
144 /*SANE_I18N ("Double letter 11x17 in"), */
145 /*SANE_I18N ("B4"), */
146 SANE_I18N ("B5"),
147 SANE_I18N ("B6"),
148 SANE_I18N ("Legal"),
149 NULL
150 };
151
152 static const unsigned paper_val[] = { 0, 1, 2, 3, 4, 5, 6, 7,
153 9, 12, 13, 14, 15
154 };
155
156 struct paper_size
157 {
158 int width;
159 int height;
160 };
161 static const struct paper_size paper_sizes[] = {
162 {210, 297}, /* User defined, default=A4 */
163 {54, 90}, /* Business card */
164 {80, 170}, /* Check (China business) */
165 {297, 420}, /* A3 */
166 {210, 297}, /* A4 */
167 {148, 210}, /* A5 */
168 {105, 148}, /* A6 */
169 {215, 280}, /* US Letter 8.5 x 11 in */
170 {280, 432}, /* Double Letter 11 x 17 in */
171 {250, 353}, /* B4 */
172 {176, 250}, /* B5 */
173 {125, 176}, /* B6 */
174 {215, 355} /* US Legal */
175 };
176
177 #define MIN_WIDTH 48
178 #define MIN_LENGTH 70
179 #define MAX_WIDTH 297
180 #define MAX_LENGTH 432
181
182 #define MAX_WIDTH_A4 227
183 #define MAX_LENGTH_A4 432
184
185 static SANE_Range tl_x_range = { 0, MAX_WIDTH - MIN_WIDTH, 0 };
186 static SANE_Range tl_y_range = { 0, MAX_LENGTH - MIN_LENGTH, 0 };
187 static SANE_Range br_x_range = { MIN_WIDTH, MAX_WIDTH, 0 };
188 static SANE_Range br_y_range = { MIN_LENGTH, MAX_LENGTH, 0 };
189
190 static SANE_Range tl_x_range_A4 = { 0, MAX_WIDTH_A4 - MIN_WIDTH, 0 };
191 static SANE_Range tl_y_range_A4 = { 0, MAX_LENGTH_A4 - MIN_LENGTH, 0 };
192 static SANE_Range br_x_range_A4 = { MIN_WIDTH, MAX_WIDTH_A4, 0 };
193 static SANE_Range br_y_range_A4 = { MIN_LENGTH, MAX_LENGTH_A4, 0 };
194
195 static SANE_Range byte_value_range = { 0, 255, 0 };
196 static SANE_Range compression_value_range = { 1, 0x64, 0 };
197
198 /* List of image emphasis options, 5 steps */
199 static SANE_String_Const image_emphasis_list[] = {
200 SANE_I18N ("none"),
201 SANE_I18N ("low"),
202 SANE_I18N ("medium"),
203 SANE_I18N ("high"),
204 SANE_I18N ("smooth"),
205 NULL
206 };
207
208 /* List of gamma */
209 static SANE_String_Const gamma_list[] = {
210 SANE_I18N ("normal"),
211 SANE_I18N ("crt"),
212 NULL
213 };
214 static unsigned gamma_val[] = { 0, 1 };
215
216 /* List of lamp color dropout */
217 static SANE_String_Const lamp_list[] = {
218 SANE_I18N ("normal"),
219 SANE_I18N ("red"),
220 SANE_I18N ("green"),
221 SANE_I18N ("blue"),
222 NULL
223 };
224 static SANE_String_Const dfeed_sence_list[] = {
225 SANE_I18N ("Normal"),
226 SANE_I18N ("High sensitivity"),
227 SANE_I18N ("Low sensitivity"),
228 NULL
229 };
230
231 /* Lists of supported halftone. They are only valid with
232 * for the Black&White mode. */
233 static SANE_String_Const halftone_pattern[] = {
234 SANE_I18N ("bayer_64"),
235 SANE_I18N ("bayer_16"),
236 SANE_I18N ("halftone_32"),
237 SANE_I18N ("halftone_64"),
238 SANE_I18N ("err_diffusion"),
239 NULL
240 };
241
242 /* Stapled document */
243 static SANE_String_Const stapeled_list[] = {
244 SANE_I18N ("No detection"),
245 SANE_I18N ("Normal mode"),
246 SANE_I18N ("Enhanced mode"),
247 NULL
248 };
249
250
251 /* List of automatic threshold options */
252 static SANE_String_Const automatic_threshold_list[] = {
253 SANE_I18N ("normal"),
254 SANE_I18N ("light"),
255 SANE_I18N ("dark"),
256 NULL
257 };
258 static const int automatic_threshold_val[] = {
259 0,
260 0x11,
261 0x1f
262 };
263
264 /* List of white level base. */
265 static SANE_String_Const white_level_list[] = {
266 SANE_I18N ("From scanner"),
267 SANE_I18N ("From paper"),
268 SANE_I18N ("Automatic"),
269 NULL
270 };
271 static const int white_level_val[] = {
272 0x00,
273 0x80,
274 0x81
275 };
276
277 /* List of noise reduction options. */
278 static SANE_String_Const noise_reduction_list[] = {
279 SANE_I18N ("default"),
280 "1x1",
281 "2x2",
282 "3x3",
283 "4x4",
284 "5x5",
285 NULL
286 };
287
288 /* Reset the options for that scanner. */
289 void
kvs40xx_init_options(struct scanner * s)290 kvs40xx_init_options (struct scanner *s)
291 {
292 int i;
293 SANE_Option_Descriptor *o;
294 /* Pre-initialize the options. */
295 memset (s->opt, 0, sizeof (s->opt));
296 memset (s->val, 0, sizeof (s->val));
297
298 for (i = 0; i < NUM_OPTIONS; i++)
299 {
300 s->opt[i].size = sizeof (SANE_Word);
301 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
302 }
303
304 /* Number of options. */
305 o = &s->opt[NUM_OPTS];
306 o->name = "";
307 o->title = SANE_TITLE_NUM_OPTIONS;
308 o->desc = SANE_DESC_NUM_OPTIONS;
309 o->type = SANE_TYPE_INT;
310 o->cap = SANE_CAP_SOFT_DETECT;
311 s->val[NUM_OPTS].w = NUM_OPTIONS;
312
313 /* Mode group */
314 o = &s->opt[MODE_GROUP];
315 o->title = SANE_I18N ("Scan Mode");
316 o->desc = ""; /* not valid for a group */
317 o->type = SANE_TYPE_GROUP;
318 o->cap = 0;
319 o->size = 0;
320 o->constraint_type = SANE_CONSTRAINT_NONE;
321
322 /* Scanner supported modes */
323 o = &s->opt[MODE];
324 o->name = SANE_NAME_SCAN_MODE;
325 o->title = SANE_TITLE_SCAN_MODE;
326 o->desc = SANE_DESC_SCAN_MODE;
327 o->type = SANE_TYPE_STRING;
328 o->size = max_string_size (mode_list);
329 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
330 o->constraint.string_list = mode_list;
331 s->val[MODE].s = malloc (o->size);
332 strcpy (s->val[MODE].s, mode_list[2]);
333
334 /* X and Y resolution */
335 o = &s->opt[RESOLUTION];
336 o->name = SANE_NAME_SCAN_RESOLUTION;
337 o->title = SANE_TITLE_SCAN_RESOLUTION;
338 o->desc = SANE_DESC_SCAN_RESOLUTION;
339 o->type = SANE_TYPE_INT;
340 o->unit = SANE_UNIT_DPI;
341 o->constraint_type = SANE_CONSTRAINT_RANGE;
342 o->constraint.range = &resolutions_range;
343 s->val[RESOLUTION].w = 100;
344
345 /* Duplex */
346 o = &s->opt[DUPLEX];
347 o->name = "duplex";
348 o->title = SANE_I18N ("Duplex");
349 o->desc = SANE_I18N ("Enable Duplex (Dual-Sided) Scanning");
350 o->type = SANE_TYPE_BOOL;
351 o->unit = SANE_UNIT_NONE;
352 s->val[DUPLEX].w = SANE_FALSE;
353
354 /*FIXME
355 if (!s->support_info.support_duplex)
356 o->cap |= SANE_CAP_INACTIVE;
357 */
358
359 /* Feeder mode */
360 o = &s->opt[FEEDER_MODE];
361 o->name = "feeder-mode";
362 o->title = SANE_I18N ("Feeder mode");
363 o->desc = SANE_I18N ("Sets the feeding mode");
364 o->type = SANE_TYPE_STRING;
365 o->size = max_string_size (feeder_mode_list);
366 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
367 o->constraint.string_list = feeder_mode_list;
368 s->val[FEEDER_MODE].s = malloc (o->size);
369 strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
370
371 /* Scan source */
372 o = &s->opt[SOURCE];
373 o->name = SANE_NAME_SCAN_SOURCE;
374 o->title = SANE_TITLE_SCAN_SOURCE;
375 o->desc = SANE_DESC_SCAN_SOURCE;
376 o->type = SANE_TYPE_STRING;
377 o->size = max_string_size (source_list);
378 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
379 o->constraint.string_list = source_list;
380 s->val[SOURCE].s = malloc (o->size);
381 strcpy (s->val[SOURCE].s, source_list[0]);
382 if (s->id != KV_S7075C)
383 o->cap |= SANE_CAP_INACTIVE;
384
385 /* Length control */
386 o = &s->opt[LENGTHCTL];
387 o->name = "length-control";
388 o->title = SANE_I18N ("Length control mode");
389 o->desc =
390 SANE_I18N
391 ("Length Control Mode causes the scanner to read the shorter of either the length of the actual"
392 " paper or logical document length");
393 o->type = SANE_TYPE_BOOL;
394 o->unit = SANE_UNIT_NONE;
395 s->val[LENGTHCTL].w = SANE_FALSE;
396
397 o = &s->opt[LONG_PAPER];
398 o->name = "long-paper";
399 o->title = SANE_I18N ("Long paper mode");
400 o->desc = SANE_I18N ("Long Paper Mode is a mode that the scanner "
401 "reads the image after it divides long paper "
402 "by the length which is set in Document Size option.");
403 o->type = SANE_TYPE_BOOL;
404 o->unit = SANE_UNIT_NONE;
405 s->val[LONG_PAPER].w = SANE_FALSE;
406 o->cap |= SANE_CAP_INACTIVE;
407
408 /* Manual feed */
409 o = &s->opt[MANUALFEED];
410 o->name = "manual-feed";
411 o->title = SANE_I18N ("Manual feed mode");
412 o->desc = SANE_I18N ("Sets the manual feed mode");
413 o->type = SANE_TYPE_STRING;
414 o->size = max_string_size (manual_feed_list);
415 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
416 o->constraint.string_list = manual_feed_list;
417 s->val[MANUALFEED].s = malloc (o->size);
418 strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
419
420 /*Manual feed timeout */
421 o = &s->opt[FEED_TIMEOUT];
422 o->name = "feed-timeout";
423 o->title = SANE_I18N ("Manual feed timeout");
424 o->desc = SANE_I18N ("Sets the manual feed timeout in seconds");
425 o->type = SANE_TYPE_INT;
426 o->unit = SANE_UNIT_NONE;
427 o->size = sizeof (SANE_Int);
428 o->constraint_type = SANE_CONSTRAINT_RANGE;
429 o->constraint.range = &(byte_value_range);
430 o->cap |= SANE_CAP_INACTIVE;
431 s->val[FEED_TIMEOUT].w = 30;
432
433 /* Double feed */
434 o = &s->opt[DBLFEED];
435 o->name = "dfeed";
436 o->title = SANE_I18N ("Double feed detection");
437 o->desc = SANE_I18N ("Enable/Disable double feed detection");
438 o->type = SANE_TYPE_BOOL;
439 o->unit = SANE_UNIT_NONE;
440 s->val[DBLFEED].w = SANE_FALSE;
441
442 o = &s->opt[DFEED_SENCE];
443 o->name = "dfeed-sense";
444 o->title = SANE_I18N ("Double feed detector sensitivity");
445 o->desc = SANE_I18N ("Set the double feed detector sensitivity");
446 o->type = SANE_TYPE_STRING;
447 o->size = max_string_size (dfeed_sence_list);
448 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
449 o->constraint.string_list = dfeed_sence_list;
450 s->val[DFEED_SENCE].s = malloc (o->size);
451 strcpy (s->val[DFEED_SENCE].s, dfeed_sence_list[0]);
452 o->cap |= SANE_CAP_INACTIVE;
453
454 o = &s->opt[DFSTOP];
455 o->name = "dfstop";
456 o->title = SANE_I18N ("Do not stop after double feed detection");
457 o->desc = SANE_I18N ("Do not stop after double feed detection");
458 o->type = SANE_TYPE_BOOL;
459 o->unit = SANE_UNIT_NONE;
460 s->val[DFSTOP].w = SANE_FALSE;
461 o->cap |= SANE_CAP_INACTIVE;
462
463 o = &s->opt[DFEED_L];
464 o->name = "dfeed_l";
465 o->title = SANE_I18N ("Ignore left double feed sensor");
466 o->desc = SANE_I18N ("Ignore left double feed sensor");
467 o->type = SANE_TYPE_BOOL;
468 o->unit = SANE_UNIT_NONE;
469 s->val[DFEED_L].w = SANE_FALSE;
470 o->cap |= SANE_CAP_INACTIVE;
471
472 o = &s->opt[DFEED_C];
473 o->name = "dfeed_c";
474 o->title = SANE_I18N ("Ignore center double feed sensor");
475 o->desc = SANE_I18N ("Ignore center double feed sensor");
476 o->type = SANE_TYPE_BOOL;
477 o->unit = SANE_UNIT_NONE;
478 s->val[DFEED_C].w = SANE_FALSE;
479 o->cap |= SANE_CAP_INACTIVE;
480
481 o = &s->opt[DFEED_R];
482 o->name = "dfeed_r";
483 o->title = SANE_I18N ("Ignore right double feed sensor");
484 o->desc = SANE_I18N ("Ignore right double feed sensor");
485 o->type = SANE_TYPE_BOOL;
486 o->unit = SANE_UNIT_NONE;
487 s->val[DFEED_R].w = SANE_FALSE;
488 o->cap |= SANE_CAP_INACTIVE;
489
490 /* Fit to page */
491 o = &s->opt[FIT_TO_PAGE];
492 o->name = SANE_I18N ("fit-to-page");
493 o->title = SANE_I18N ("Fit to page");
494 o->desc = SANE_I18N ("Scanner shrinks image to fit scanned page");
495 o->type = SANE_TYPE_BOOL;
496 o->unit = SANE_UNIT_NONE;
497 s->val[FIT_TO_PAGE].w = SANE_FALSE;
498
499 /* Geometry group */
500 o = &s->opt[GEOMETRY_GROUP];
501 o->title = SANE_I18N ("Geometry");
502 o->desc = ""; /* not valid for a group */
503 o->type = SANE_TYPE_GROUP;
504 o->cap = 0;
505 o->size = 0;
506 o->constraint_type = SANE_CONSTRAINT_NONE;
507
508 /* Paper sizes list */
509 o = &s->opt[PAPER_SIZE];
510 o->name = "paper-size";
511 o->title = SANE_I18N ("Paper size");
512 o->desc = SANE_I18N ("Physical size of the paper in the ADF");
513 o->type = SANE_TYPE_STRING;
514 o->constraint.string_list =
515 s->id == KV_S4085CL || s->id == KV_S4065CL ? paper_list_woA3 : paper_list;
516
517
518 o->size = max_string_size (o->constraint.string_list);
519 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
520 s->val[PAPER_SIZE].s = malloc (o->size);
521 strcpy (s->val[PAPER_SIZE].s, SANE_I18N ("A4"));
522
523 /* Landscape */
524 o = &s->opt[LANDSCAPE];
525 o->name = "landscape";
526 o->title = SANE_I18N ("Landscape");
527 o->desc =
528 SANE_I18N ("Set paper position : "
529 "true for landscape, false for portrait");
530 o->type = SANE_TYPE_BOOL;
531 o->unit = SANE_UNIT_NONE;
532 s->val[LANDSCAPE].w = SANE_FALSE;
533
534 /* Upper left X */
535 o = &s->opt[TL_X];
536 o->name = SANE_NAME_SCAN_TL_X;
537 o->title = SANE_TITLE_SCAN_TL_X;
538 o->desc = SANE_DESC_SCAN_TL_X;
539 o->type = SANE_TYPE_INT;
540 o->unit = SANE_UNIT_MM;
541 o->constraint_type = SANE_CONSTRAINT_RANGE;
542 o->constraint.range =
543 (s->id == KV_S4085CL || s->id == KV_S4065CL)
544 ? &tl_x_range_A4 : &tl_x_range;
545 o->cap |= SANE_CAP_INACTIVE;
546 s->val[TL_X].w = 0;
547
548 /* Upper left Y */
549 o = &s->opt[TL_Y];
550 o->name = SANE_NAME_SCAN_TL_Y;
551 o->title = SANE_TITLE_SCAN_TL_Y;
552 o->desc = SANE_DESC_SCAN_TL_Y;
553 o->type = SANE_TYPE_INT;
554 o->unit = SANE_UNIT_MM;
555 o->constraint_type = SANE_CONSTRAINT_RANGE;
556 o->constraint.range =
557 (s->id == KV_S4085CL || s->id == KV_S4065CL)
558 ? &tl_y_range_A4 : &tl_y_range;
559 o->cap |= SANE_CAP_INACTIVE;
560 s->val[TL_Y].w = 0;
561
562 /* Bottom-right x */
563 o = &s->opt[BR_X];
564 o->name = SANE_NAME_SCAN_BR_X;
565 o->title = SANE_TITLE_SCAN_BR_X;
566 o->desc = SANE_DESC_SCAN_BR_X;
567 o->type = SANE_TYPE_INT;
568 o->unit = SANE_UNIT_MM;
569 o->constraint_type = SANE_CONSTRAINT_RANGE;
570 o->constraint.range =
571 (s->id == KV_S4085CL || s->id == KV_S4065CL)
572 ? &br_x_range_A4 : &br_x_range;
573 o->cap |= SANE_CAP_INACTIVE;
574 s->val[BR_X].w = 210;
575
576 /* Bottom-right y */
577 o = &s->opt[BR_Y];
578 o->name = SANE_NAME_SCAN_BR_Y;
579 o->title = SANE_TITLE_SCAN_BR_Y;
580 o->desc = SANE_DESC_SCAN_BR_Y;
581 o->type = SANE_TYPE_INT;
582 o->unit = SANE_UNIT_MM;
583 o->constraint_type = SANE_CONSTRAINT_RANGE;
584 o->constraint.range =
585 (s->id == KV_S4085CL || s->id == KV_S4065CL)
586 ? &br_y_range_A4 : &br_y_range;
587 o->cap |= SANE_CAP_INACTIVE;
588 s->val[BR_Y].w = 297;
589
590 /* Enhancement group */
591 o = &s->opt[ADVANCED_GROUP];
592 o->title = SANE_I18N ("Advanced");
593 o->desc = ""; /* not valid for a group */
594 o->type = SANE_TYPE_GROUP;
595 o->cap = SANE_CAP_ADVANCED;
596 o->size = 0;
597 o->constraint_type = SANE_CONSTRAINT_NONE;
598
599 /* Brightness */
600 o = &s->opt[BRIGHTNESS];
601 o->name = SANE_NAME_BRIGHTNESS;
602 o->title = SANE_TITLE_BRIGHTNESS;
603 o->desc = SANE_DESC_BRIGHTNESS;
604 o->type = SANE_TYPE_INT;
605 o->unit = SANE_UNIT_NONE;
606 o->size = sizeof (SANE_Int);
607 o->constraint_type = SANE_CONSTRAINT_RANGE;
608 o->constraint.range = &(byte_value_range);
609 s->val[BRIGHTNESS].w = 128;
610
611 /* Contrast */
612 o = &s->opt[CONTRAST];
613 o->name = SANE_NAME_CONTRAST;
614 o->title = SANE_TITLE_CONTRAST;
615 o->desc = SANE_DESC_CONTRAST;
616 o->type = SANE_TYPE_INT;
617 o->unit = SANE_UNIT_NONE;
618 o->size = sizeof (SANE_Int);
619 o->constraint_type = SANE_CONSTRAINT_RANGE;
620 o->constraint.range = &(byte_value_range);
621 s->val[CONTRAST].w = 128;
622
623 /* threshold */
624 o = &s->opt[THRESHOLD];
625 o->name = SANE_NAME_THRESHOLD;
626 o->title = SANE_TITLE_THRESHOLD;
627 o->desc = SANE_DESC_THRESHOLD;
628 o->type = SANE_TYPE_INT;
629 o->size = sizeof (SANE_Int);
630 o->constraint_type = SANE_CONSTRAINT_RANGE;
631 o->constraint.range = &(byte_value_range);
632 s->val[THRESHOLD].w = 128;
633 o->cap |= SANE_CAP_INACTIVE;
634
635 o = &s->opt[AUTOMATIC_THRESHOLD];
636 o->name = "athreshold";
637 o->title = SANE_I18N ("Automatic threshold mode");
638 o->desc = SANE_I18N ("Sets the automatic threshold mode");
639 o->type = SANE_TYPE_STRING;
640 o->size = max_string_size (automatic_threshold_list);
641 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
642 o->constraint.string_list = automatic_threshold_list;
643 s->val[AUTOMATIC_THRESHOLD].s = malloc (o->size);
644 strcpy (s->val[AUTOMATIC_THRESHOLD].s, automatic_threshold_list[0]);
645 o->cap |= SANE_CAP_INACTIVE;
646
647 /* Image emphasis */
648 o = &s->opt[IMAGE_EMPHASIS];
649 o->name = "image-emphasis";
650 o->title = SANE_I18N ("Image emphasis");
651 o->desc = SANE_I18N ("Sets the image emphasis");
652 o->type = SANE_TYPE_STRING;
653 o->size = max_string_size (image_emphasis_list);
654 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
655 o->constraint.string_list = image_emphasis_list;
656 s->val[IMAGE_EMPHASIS].s = malloc (o->size);
657 strcpy (s->val[IMAGE_EMPHASIS].s, image_emphasis_list[0]);;
658 o->cap |= SANE_CAP_INACTIVE;
659
660 /* Gamma */
661 o = &s->opt[GAMMA_CORRECTION];
662 o->name = "gamma-cor";
663 o->title = SANE_I18N ("Gamma correction");
664 o->desc = SANE_I18N ("Gamma correction");
665 o->type = SANE_TYPE_STRING;
666 o->size = max_string_size (gamma_list);
667 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
668 o->constraint.string_list = gamma_list;
669 s->val[GAMMA_CORRECTION].s = malloc (o->size);
670 strcpy (s->val[GAMMA_CORRECTION].s, gamma_list[0]);
671 o->cap |= SANE_CAP_INACTIVE;
672
673 /* Lamp color dropout */
674 o = &s->opt[LAMP];
675 o->name = "lamp-color";
676 o->title = SANE_I18N ("Lamp color");
677 o->desc = SANE_I18N ("Sets the lamp color (color dropout)");
678 o->type = SANE_TYPE_STRING;
679 o->size = max_string_size (lamp_list);
680 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
681 o->constraint.string_list = lamp_list;
682 s->val[LAMP].s = malloc (o->size);
683 strcpy (s->val[LAMP].s, lamp_list[0]);
684
685 /* Inverse image */
686 o = &s->opt[INVERSE];
687 o->name = "inverse";
688 o->title = SANE_I18N ("Inverse Image");
689 o->desc = SANE_I18N ("Inverse image in B/W mode");
690 o->type = SANE_TYPE_BOOL;
691 o->unit = SANE_UNIT_NONE;
692 o->cap |= SANE_CAP_INACTIVE;
693
694 /* Halftone pattern */
695 o = &s->opt[HALFTONE_PATTERN];
696 o->name = SANE_NAME_HALFTONE_PATTERN;
697 o->title = SANE_TITLE_HALFTONE_PATTERN;
698 o->desc = SANE_DESC_HALFTONE_PATTERN;
699 o->type = SANE_TYPE_STRING;
700 o->size = max_string_size (halftone_pattern);
701 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
702 o->constraint.string_list = halftone_pattern;
703 s->val[HALFTONE_PATTERN].s = malloc (o->size);
704 strcpy (s->val[HALFTONE_PATTERN].s, halftone_pattern[0]);
705 o->cap |= SANE_CAP_INACTIVE;
706
707 /* JPEG Compression */
708 o = &s->opt[COMPRESSION];
709 o->name = "jpeg";
710 o->title = SANE_I18N ("JPEG compression");
711 o->desc =
712 SANE_I18N
713 ("JPEG compression (your application must be able to uncompress)");
714 o->type = SANE_TYPE_BOOL;
715 o->unit = SANE_UNIT_NONE;
716
717 /* Compression parameter */
718 o = &s->opt[COMPRESSION_PAR];
719 o->name = "comp_arg";
720 o->title = "Compression Argument";
721 o->desc = "Compression Argument (Q parameter for JPEG)";
722 o->type = SANE_TYPE_INT;
723 o->size = sizeof (SANE_Int);
724 o->constraint_type = SANE_CONSTRAINT_RANGE;
725 o->constraint.range = &(compression_value_range);
726 s->val[COMPRESSION_PAR].w = 0x4b;
727 o->cap |= SANE_CAP_INACTIVE;
728
729 /* Stapled document */
730 o = &s->opt[STAPELED_DOC];
731 o->name = "stapeled_doc";
732 o->title = SANE_I18N ("Detect stapled document");
733 o->desc = SANE_I18N ("Detect stapled document");
734 o->type = SANE_TYPE_STRING;
735 o->size = max_string_size (stapeled_list);
736 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
737 o->constraint.string_list = stapeled_list;
738 s->val[STAPELED_DOC].s = malloc (o->size);
739 strcpy (s->val[STAPELED_DOC].s, stapeled_list[0]);
740 if (s->id == KV_S7075C)
741 o->cap |= SANE_CAP_INACTIVE;
742
743 /* White level base */
744 o = &s->opt[WHITE_LEVEL];
745 o->name = SANE_NAME_WHITE_LEVEL;
746 o->title = SANE_TITLE_WHITE_LEVEL;
747 o->desc = SANE_DESC_WHITE_LEVEL;
748 o->type = SANE_TYPE_STRING;
749 o->size = max_string_size (white_level_list);
750 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
751 o->constraint.string_list = white_level_list;
752 s->val[WHITE_LEVEL].s = malloc (o->size);
753 strcpy (s->val[WHITE_LEVEL].s, white_level_list[0]);
754 o->cap |= SANE_CAP_INACTIVE;
755
756 /* Noise reduction */
757 o = &s->opt[NOISE_REDUCTION];
758 o->name = "noise-reduction";
759 o->title = SANE_I18N ("Noise reduction");
760 o->desc = SANE_I18N ("Reduce the isolated dot noise");
761 o->type = SANE_TYPE_STRING;
762 o->size = max_string_size (noise_reduction_list);
763 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
764 o->constraint.string_list = noise_reduction_list;
765 s->val[NOISE_REDUCTION].s = malloc (o->size);
766 strcpy (s->val[NOISE_REDUCTION].s, noise_reduction_list[0]);
767 o->cap |= SANE_CAP_INACTIVE;
768
769 o = &s->opt[RED_CHROMA];
770 o->name = "red-chroma";
771 o->title = SANE_I18N ("chroma of red");
772 o->desc = SANE_I18N ("Set chroma of red");
773 o->type = SANE_TYPE_INT;
774 o->unit = SANE_UNIT_NONE;
775 o->size = sizeof (SANE_Int);
776 o->constraint_type = SANE_CONSTRAINT_RANGE;
777 o->constraint.range = &(byte_value_range);
778 s->val[RED_CHROMA].w = 0;
779
780 o = &s->opt[BLUE_CHROMA];
781 o->name = "blue chroma";
782 o->title = SANE_I18N ("chroma of blue");
783 o->desc = SANE_I18N ("Set chroma of blue");
784 o->type = SANE_TYPE_INT;
785 o->unit = SANE_UNIT_NONE;
786 o->size = sizeof (SANE_Int);
787 o->constraint_type = SANE_CONSTRAINT_RANGE;
788 o->constraint.range = &(byte_value_range);
789 s->val[BLUE_CHROMA].w = 0;
790
791 o = &s->opt[DESKEW];
792 o->name = "deskew";
793 o->title = SANE_I18N ("Skew adjustment");
794 o->desc = SANE_I18N ("Skew adjustment");
795 o->type = SANE_TYPE_BOOL;
796 o->unit = SANE_UNIT_NONE;
797 s->val[DESKEW].w = SANE_FALSE;
798 if (s->id != KV_S4085CL && s->id != KV_S4085CW)
799 o->cap |= SANE_CAP_INACTIVE;
800
801 o = &s->opt[STOP_SKEW];
802 o->name = "stop-skew";
803 o->title = SANE_I18N ("Stop scanner if a sheet is skewed");
804 o->desc = SANE_I18N ("Scanner will stop if a sheet is skewed");
805 o->type = SANE_TYPE_BOOL;
806 o->unit = SANE_UNIT_NONE;
807 s->val[STOP_SKEW].w = SANE_FALSE;
808
809 o = &s->opt[CROP];
810 o->name = "crop";
811 o->title = SANE_I18N ("Crop actual image area");
812 o->desc = SANE_I18N ("Scanner will automatically detect image area and crop to it");
813 o->type = SANE_TYPE_BOOL;
814 o->unit = SANE_UNIT_NONE;
815 s->val[CROP].w = SANE_FALSE;
816 if (s->id != KV_S4085CL && s->id != KV_S4085CW)
817 o->cap |= SANE_CAP_INACTIVE;
818
819 o = &s->opt[MIRROR];
820 o->name = "mirror";
821 o->title = SANE_I18N ("Mirror image");
822 o->desc = SANE_I18N ("Left/right mirror image");
823 o->type = SANE_TYPE_BOOL;
824 o->unit = SANE_UNIT_NONE;
825 s->val[MIRROR].w = SANE_FALSE;
826
827 o = &s->opt[TOPPOS];
828 o->name = "toppos";
829 o->title = SANE_I18N ("Addition of space in top position");
830 o->desc = SANE_I18N ("Addition of space in top position");
831 o->type = SANE_TYPE_BOOL;
832 o->unit = SANE_UNIT_NONE;
833 s->val[TOPPOS].w = SANE_FALSE;
834
835 o = &s->opt[BTMPOS];
836 o->name = "btmpos";
837 o->title = SANE_I18N ("Addition of space in bottom position");
838 o->desc = SANE_I18N ("Addition of space in bottom position");
839 o->type = SANE_TYPE_BOOL;
840 o->unit = SANE_UNIT_NONE;
841 s->val[BTMPOS].w = SANE_FALSE;
842 }
843
844
845 /* Lookup a string list from one array and return its index. */
846 static int
str_index(const SANE_String_Const * list,SANE_String_Const name)847 str_index (const SANE_String_Const * list, SANE_String_Const name)
848 {
849 int index;
850 index = 0;
851 while (list[index])
852 {
853 if (!strcmp (list[index], name))
854 return (index);
855 index++;
856 }
857 return (-1); /* not found */
858 }
859
860 /* Control option */
861 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)862 sane_control_option (SANE_Handle handle, SANE_Int option,
863 SANE_Action action, void *val, SANE_Int * info)
864 {
865 int i;
866 SANE_Status status;
867 SANE_Word cap;
868 struct scanner *s = (struct scanner *) handle;
869
870 if (info)
871 *info = 0;
872
873 if (option < 0 || option >= NUM_OPTIONS)
874 return SANE_STATUS_UNSUPPORTED;
875
876 cap = s->opt[option].cap;
877 if (!SANE_OPTION_IS_ACTIVE (cap))
878 return SANE_STATUS_UNSUPPORTED;
879
880 if (action == SANE_ACTION_GET_VALUE)
881 {
882 if (s->opt[option].type == SANE_TYPE_STRING)
883 {
884 DBG (DBG_INFO,
885 "sane_control_option: reading opt[%d] = %s\n",
886 option, s->val[option].s);
887 strcpy (val, s->val[option].s);
888 }
889 else
890 {
891 *(SANE_Word *) val = s->val[option].w;
892 DBG (DBG_INFO,
893 "sane_control_option: reading opt[%d] = %d\n",
894 option, s->val[option].w);
895 }
896 return SANE_STATUS_GOOD;
897
898 }
899 else if (action == SANE_ACTION_SET_VALUE)
900 {
901 if (!SANE_OPTION_IS_SETTABLE (cap))
902 return SANE_STATUS_INVAL;
903
904 status = sanei_constrain_value (s->opt + option, val, info);
905 if (status != SANE_STATUS_GOOD)
906 return status;
907
908 if (s->opt[option].type == SANE_TYPE_STRING)
909 {
910 if (!strcmp (val, s->val[option].s))
911 return SANE_STATUS_GOOD;
912 DBG (DBG_INFO,
913 "sane_control_option: writing opt[%d] = %s\n",
914 option, (SANE_String_Const) val);
915 }
916 else
917 {
918 if (*(SANE_Word *) val == s->val[option].w)
919 return SANE_STATUS_GOOD;
920 DBG (DBG_INFO,
921 "sane_control_option: writing opt[%d] = %d\n",
922 option, *(SANE_Word *) val);
923 }
924
925 switch (option)
926 {
927 /* Side-effect options */
928 case RESOLUTION:
929 s->val[option].w = *(SANE_Word *) val;
930 if (info)
931 *info |= SANE_INFO_RELOAD_PARAMS;
932 return SANE_STATUS_GOOD;
933
934 case TL_Y:
935 if ((*(SANE_Word *) val) + MIN_LENGTH <=
936 s->val[BR_Y].w &&
937 !check_area (s, s->val[TL_X].w, *(SANE_Word *) val,
938 s->val[BR_X].w, s->val[BR_Y].w))
939 {
940 s->val[option].w = *(SANE_Word *) val;
941 if (info)
942 *info |= SANE_INFO_RELOAD_PARAMS;
943 }
944 else if (info)
945 *info |= SANE_INFO_INEXACT |
946 SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
947 return SANE_STATUS_GOOD;
948 case BR_Y:
949 if ((*(SANE_Word *) val) >=
950 s->val[TL_Y].w + MIN_LENGTH
951 && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
952 s->val[BR_X].w, *(SANE_Word *) val))
953 {
954 s->val[option].w = *(SANE_Word *) val;
955 if (info)
956 *info |= SANE_INFO_RELOAD_PARAMS;
957 }
958 else if (info)
959 *info |= SANE_INFO_INEXACT |
960 SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
961 return SANE_STATUS_GOOD;
962
963 case TL_X:
964 if ((*(SANE_Word *) val) + MIN_WIDTH <=
965 s->val[BR_X].w &&
966 !check_area (s, *(SANE_Word *) val, s->val[TL_Y].w,
967 s->val[BR_X].w, s->val[BR_Y].w))
968 {
969 s->val[option].w = *(SANE_Word *) val;
970 if (info)
971 *info |= SANE_INFO_RELOAD_PARAMS;
972 }
973 else if (info)
974 *info |= SANE_INFO_INEXACT |
975 SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
976 return SANE_STATUS_GOOD;
977
978 case BR_X:
979 if (*(SANE_Word *) val >=
980 s->val[TL_X].w + MIN_WIDTH
981 && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w,
982 *(SANE_Word *) val, s->val[BR_Y].w))
983 {
984 s->val[option].w = *(SANE_Word *) val;
985 if (info)
986 *info |= SANE_INFO_RELOAD_PARAMS;
987 }
988 else if (info)
989 *info |= SANE_INFO_INEXACT |
990 SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
991 return SANE_STATUS_GOOD;
992
993 case LANDSCAPE:
994 s->val[option].w = *(SANE_Word *) val;
995 if (info)
996 *info |= SANE_INFO_RELOAD_PARAMS;
997 return SANE_STATUS_GOOD;
998
999 /* Side-effect free options */
1000 case CONTRAST:
1001 case BRIGHTNESS:
1002 case DUPLEX:
1003 case LENGTHCTL:
1004 case LONG_PAPER:
1005 case FIT_TO_PAGE:
1006 case THRESHOLD:
1007 case INVERSE:
1008 case COMPRESSION_PAR:
1009 case DFSTOP:
1010 case DFEED_L:
1011 case DFEED_C:
1012 case DFEED_R:
1013 case STOP_SKEW:
1014 case DESKEW:
1015 case MIRROR:
1016 case CROP:
1017 case TOPPOS:
1018 case BTMPOS:
1019 case RED_CHROMA:
1020 case BLUE_CHROMA:
1021 s->val[option].w = *(SANE_Word *) val;
1022 return SANE_STATUS_GOOD;
1023
1024 case FEED_TIMEOUT:
1025 s->val[option].w = *(SANE_Word *) val;
1026 return kvs40xx_set_timeout (s, s->val[option].w);
1027
1028 /* String mode */
1029 case IMAGE_EMPHASIS:
1030 case GAMMA_CORRECTION:
1031 case LAMP:
1032 case HALFTONE_PATTERN:
1033 case DFEED_SENCE:
1034 case AUTOMATIC_THRESHOLD:
1035 case WHITE_LEVEL:
1036 case NOISE_REDUCTION:
1037 strcpy (s->val[option].s, val);
1038 return SANE_STATUS_GOOD;
1039
1040 case SOURCE:
1041 strcpy (s->val[option].s, val);
1042 if (strcmp (s->val[option].s, SANE_I18N ("adf")))
1043 {
1044 strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
1045 strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
1046 s->val[DUPLEX].w = SANE_FALSE;
1047 s->val[DBLFEED].w = SANE_FALSE;
1048 s->val[BTMPOS].w = SANE_FALSE;
1049 s->val[TOPPOS].w = SANE_FALSE;
1050 s->val[STOP_SKEW].w = SANE_FALSE;
1051 s->val[LENGTHCTL].w = SANE_FALSE;
1052 s->val[LONG_PAPER].w = SANE_FALSE;
1053 s->opt[FEEDER_MODE].cap |= SANE_CAP_INACTIVE;
1054 s->opt[MANUALFEED].cap |= SANE_CAP_INACTIVE;
1055 s->opt[DUPLEX].cap |= SANE_CAP_INACTIVE;
1056 s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
1057 s->opt[BTMPOS].cap |= SANE_CAP_INACTIVE;
1058 s->opt[TOPPOS].cap |= SANE_CAP_INACTIVE;
1059 s->opt[STOP_SKEW].cap |= SANE_CAP_INACTIVE;
1060 s->opt[LENGTHCTL].cap |= SANE_CAP_INACTIVE;
1061 s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
1062 }
1063 else
1064 {
1065 s->opt[FEEDER_MODE].cap &= ~SANE_CAP_INACTIVE;
1066 s->opt[MANUALFEED].cap &= ~SANE_CAP_INACTIVE;
1067 s->opt[DUPLEX].cap &= ~SANE_CAP_INACTIVE;
1068 s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
1069 s->opt[BTMPOS].cap &= ~SANE_CAP_INACTIVE;
1070 s->opt[TOPPOS].cap &= ~SANE_CAP_INACTIVE;
1071 s->opt[STOP_SKEW].cap &= ~SANE_CAP_INACTIVE;
1072 s->opt[LENGTHCTL].cap &= ~SANE_CAP_INACTIVE;
1073 s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
1074 }
1075 if (info)
1076 *info |= SANE_INFO_RELOAD_OPTIONS;
1077
1078 return SANE_STATUS_GOOD;
1079
1080 case FEEDER_MODE:
1081 strcpy (s->val[option].s, val);
1082 if (strcmp (s->val[option].s, SANE_I18N ("continuous")))
1083 {
1084 s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE;
1085 }
1086 else
1087 {
1088 s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE;
1089 }
1090 if (info)
1091 *info |= SANE_INFO_RELOAD_OPTIONS;
1092
1093 return SANE_STATUS_GOOD;
1094
1095 case MODE:
1096 strcpy (s->val[option].s, val);
1097 if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART))
1098 {
1099 s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
1100 s->opt[COMPRESSION].cap |= SANE_CAP_INACTIVE;
1101 s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
1102 s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
1103 s->opt[HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
1104
1105 s->opt[AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
1106 s->opt[WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE;
1107 s->opt[NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE;
1108 s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;
1109 s->opt[RED_CHROMA].cap |= SANE_CAP_INACTIVE;
1110 s->opt[BLUE_CHROMA].cap |= SANE_CAP_INACTIVE;
1111 }
1112 else
1113 {
1114 s->opt[COMPRESSION].cap &= ~SANE_CAP_INACTIVE;
1115 s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;
1116
1117 s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE;
1118 s->opt[INVERSE].cap |= SANE_CAP_INACTIVE;
1119 s->opt[HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
1120
1121 s->opt[AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1122 s->opt[WHITE_LEVEL].cap |= SANE_CAP_INACTIVE;
1123 s->opt[NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE;
1124 s->opt[RED_CHROMA].cap &= ~SANE_CAP_INACTIVE;
1125 s->opt[BLUE_CHROMA].cap &= ~SANE_CAP_INACTIVE;
1126 }
1127
1128 if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY))
1129 {
1130 s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE;
1131
1132 s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE;
1133 }
1134 else
1135 {
1136 s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
1137 }
1138
1139 if (info)
1140 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1141
1142 return SANE_STATUS_GOOD;
1143
1144 case MANUALFEED:
1145 strcpy (s->val[option].s, val);
1146 if (strcmp (s->val[option].s, manual_feed_list[0]) == 0) /* off */
1147 s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
1148 else
1149 s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE;
1150 if (info)
1151 *info |= SANE_INFO_RELOAD_OPTIONS;
1152
1153 return SANE_STATUS_GOOD;
1154
1155 case STAPELED_DOC:
1156 strcpy (s->val[option].s, val);
1157 if (strcmp (s->val[option].s, stapeled_list[0]) == 0)
1158 {
1159 s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE;
1160 s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
1161 s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
1162 s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
1163 s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
1164 s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
1165 s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
1166 }
1167 else
1168 {
1169 s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE;
1170 s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
1171 s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
1172 s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
1173 s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
1174 s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
1175 }
1176 if (info)
1177 *info |= SANE_INFO_RELOAD_OPTIONS;
1178
1179 return SANE_STATUS_GOOD;
1180
1181 case DBLFEED:
1182 s->val[option].w = *(SANE_Word *) val;
1183 if (!s->val[option].b)
1184 {
1185 s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE;
1186 s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE;
1187 s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE;
1188 s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE;
1189 s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE;
1190 }
1191 else
1192 {
1193 s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE;
1194 s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE;
1195 s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
1196 s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE;
1197 s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE;
1198 s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE;
1199 }
1200 if (info)
1201 *info |= SANE_INFO_RELOAD_OPTIONS;
1202
1203 return SANE_STATUS_GOOD;
1204
1205 case PAPER_SIZE:
1206 strcpy (s->val[option].s, val);
1207 i = str_index (paper_list, s->val[option].s);
1208 if (i == 0)
1209 { /*user def */
1210 s->opt[TL_X].cap &=
1211 s->opt[TL_Y].cap &=
1212 s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE;
1213 s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
1214 s->val[LANDSCAPE].w = 0;
1215 }
1216 else
1217 {
1218 s->opt[TL_X].cap |=
1219 s->opt[TL_Y].cap |=
1220 s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE;
1221 if ( /*i == 4 || */ i == 5 || i == 6 /*XXX*/
1222 || i == 10 || i == 11)
1223 { /*A4, A5, A6, B5, B6 */
1224 if ((s->id == KV_S4085CL || s->id == KV_S4065CL)
1225 && i == 4 && i == 10)
1226 { /*A4, B5 */
1227 s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
1228 s->val[LANDSCAPE].w = 0;
1229 }
1230 else
1231 s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE;
1232 }
1233 else
1234 {
1235 s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
1236 s->val[LANDSCAPE].w = 0;
1237 }
1238 }
1239 if (info)
1240 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
1241
1242 return SANE_STATUS_GOOD;
1243
1244 case COMPRESSION:
1245 s->val[option].w = *(SANE_Word *) val;
1246 if (!s->val[option].b)
1247 {
1248 s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE;
1249 }
1250 else
1251 {
1252 s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE;
1253 }
1254 if (info)
1255 *info |= SANE_INFO_RELOAD_OPTIONS;
1256
1257 return SANE_STATUS_GOOD;
1258 }
1259 }
1260
1261
1262 return SANE_STATUS_UNSUPPORTED;
1263 }
1264
1265 void
kvs40xx_init_window(struct scanner * s,struct window * wnd,int wnd_id)1266 kvs40xx_init_window (struct scanner *s, struct window *wnd, int wnd_id)
1267 {
1268 int paper = str_index (paper_list, s->val[PAPER_SIZE].s), i;
1269 memset (wnd, 0, sizeof (struct window));
1270 copy16 (wnd->window_descriptor_block_length, cpu2be16 (66));
1271
1272 wnd->window_identifier = wnd_id;
1273 copy16 (wnd->x_resolution, cpu2be16 (s->val[RESOLUTION].w));
1274 copy16 (wnd->y_resolution, cpu2be16 (s->val[RESOLUTION].w));
1275 if (!paper)
1276 {
1277 copy32 (wnd->upper_left_x,
1278 cpu2be32 (mm2scanner_units (s->val[TL_X].w)));
1279 copy32 (wnd->upper_left_y,
1280 cpu2be32 (mm2scanner_units (s->val[TL_Y].w)));
1281 copy32 (wnd->document_width,
1282 cpu2be32 (mm2scanner_units (s->val[BR_X].w)));
1283 copy32 (wnd->width,
1284 cpu2be32 (mm2scanner_units (s->val[BR_X].w - s->val[TL_X].w)));
1285 copy32 (wnd->document_length, cpu2be32 (mm2scanner_units
1286 (s->val[BR_Y].w)));
1287 copy32 (wnd->length,
1288 cpu2be32 (mm2scanner_units (s->val[BR_Y].w - s->val[TL_Y].w)));
1289 }
1290 else
1291 {
1292 u32 w = cpu2be32 (mm2scanner_units (paper_sizes[paper].width));
1293 u32 h = cpu2be32 (mm2scanner_units (paper_sizes[paper].height));
1294 copy32 (wnd->upper_left_x, cpu2be32 (mm2scanner_units (0)));
1295 copy32 (wnd->upper_left_y, cpu2be32 (mm2scanner_units (0)));
1296 if (!s->val[LANDSCAPE].b)
1297 {
1298 copy32 (wnd->width, w);
1299 copy32 (wnd->length, h);
1300 copy32 (wnd->document_width, w);
1301 copy32 (wnd->document_length, h);
1302 }
1303 else
1304 {
1305 copy32 (wnd->width, h);
1306 copy32 (wnd->length, w);
1307 copy32 (wnd->document_width, h);
1308 copy32 (wnd->document_length, w);
1309 }
1310 }
1311 wnd->brightness = s->val[BRIGHTNESS].w;
1312 wnd->threshold = s->val[THRESHOLD].w;
1313 wnd->contrast = s->val[CONTRAST].w;
1314 wnd->image_composition = mode_val[str_index (mode_list, s->val[MODE].s)];
1315 wnd->bit_per_pixel = bps_val[str_index (mode_list, s->val[MODE].s)];
1316
1317 copy16 (wnd->halftone_pattern,
1318 cpu2be16 (str_index (halftone_pattern, s->val[HALFTONE_PATTERN].s)));
1319
1320 wnd->rif_padding = s->val[INVERSE].b << 7;
1321 copy16 (wnd->bit_ordering, cpu2be16 (BIT_ORDERING));
1322 wnd->compression_type = s->val[COMPRESSION].b ? 0x81 : 0;
1323 wnd->compression_argument = s->val[COMPRESSION_PAR].w;
1324
1325 wnd->vendor_unique_identifier = 0;
1326 wnd->nobuf_fstspeed_dfstop = str_index (source_list,
1327 s->val[SOURCE].s) << 7 |
1328 str_index (stapeled_list,
1329 s->val[STAPELED_DOC].s) << 5 |
1330 s->val[STOP_SKEW].b << 4 | s->val[CROP].b << 3 | s->val[DFSTOP].b << 0;
1331
1332 wnd->mirror_image = s->val[MIRROR].b << 7 |
1333 s->val[DFEED_L].b << 2 | s->val[DFEED_C].b << 1 | s->val[DFEED_R].b << 0;
1334 wnd->image_emphasis = str_index (image_emphasis_list,
1335 s->val[IMAGE_EMPHASIS].s);
1336 wnd->gamma_correction = gamma_val[str_index (gamma_list,
1337 s->val[GAMMA_CORRECTION].s)];
1338 wnd->mcd_lamp_dfeed_sens =
1339 str_index (lamp_list, s->val[LAMP].s) << 4 |
1340 str_index (dfeed_sence_list, s->val[DFEED_SENCE].s);
1341
1342 wnd->document_size = ((paper != 0) << 7) | (s->val[LENGTHCTL].b << 6)
1343 | (s->val[LONG_PAPER].b << 5) | (s->val[LANDSCAPE].b << 4)
1344 | paper_val[paper];
1345
1346 wnd->ahead_deskew_dfeed_scan_area_fspeed_rshad =
1347 (s->val[DESKEW].b || s->val[CROP].b ? 2 : 0) << 5 | /*XXX*/
1348 s->val[DBLFEED].b << 4 | s->val[FIT_TO_PAGE].b << 2;
1349 wnd->continuous_scanning_pages =
1350 str_index (feeder_mode_list, s->val[FEEDER_MODE].s) ? 0xff : 0;
1351 wnd->automatic_threshold_mode = automatic_threshold_val
1352 [str_index (automatic_threshold_list, s->val[AUTOMATIC_THRESHOLD].s)];
1353 wnd->automatic_separation_mode = 0; /*Does not supported */
1354 wnd->standard_white_level_mode =
1355 white_level_val[str_index (white_level_list, s->val[WHITE_LEVEL].s)];
1356 wnd->b_wnr_noise_reduction =
1357 str_index (noise_reduction_list, s->val[NOISE_REDUCTION].s);
1358
1359 i = str_index (manual_feed_list, s->val[MANUALFEED].s);
1360 wnd->mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr = i << 6 |
1361 s->val[TOPPOS].b << 5 | s->val[BTMPOS].b << 4;
1362 wnd->stop_mode = 1;
1363 wnd->red_chroma = s->val[RED_CHROMA].w;
1364 wnd->blue_chroma = s->val[BLUE_CHROMA].w;
1365 }
1366
1367 /* Get scan parameters */
1368 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1369 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1370 {
1371 struct scanner *s = (struct scanner *) handle;
1372 SANE_Parameters *p = &s->params;
1373
1374 if (!s->scanning)
1375 {
1376 unsigned w, h, res = s->val[RESOLUTION].w;
1377 unsigned i = str_index (paper_list,
1378 s->val[PAPER_SIZE].s);
1379 if (i)
1380 {
1381 if (s->val[LANDSCAPE].b)
1382 {
1383 w = paper_sizes[i].height;
1384 h = paper_sizes[i].width;
1385 }
1386 else
1387 {
1388 w = paper_sizes[i].width;
1389 h = paper_sizes[i].height;
1390 }
1391 }
1392 else
1393 {
1394 w = s->val[BR_X].w - s->val[TL_X].w;
1395 h = s->val[BR_Y].w - s->val[TL_Y].w;
1396 }
1397 p->pixels_per_line = w * res / 25.4 + .5;
1398 p->lines = h * res / 25.4 + .5;
1399 }
1400
1401 p->format = !strcmp (s->val[MODE].s,
1402 SANE_VALUE_SCAN_MODE_COLOR) ? SANE_FRAME_RGB :
1403 SANE_FRAME_GRAY;
1404 p->last_frame = SANE_TRUE;
1405 p->depth = bps_val[str_index (mode_list, s->val[MODE].s)];
1406 p->bytes_per_line = p->depth * p->pixels_per_line / 8;
1407 if (p->depth > 8)
1408 p->depth = 8;
1409 if (params)
1410 memcpy (params, p, sizeof (SANE_Parameters));
1411 s->side_size = p->bytes_per_line * p->lines;
1412
1413 return SANE_STATUS_GOOD;
1414 }
1415