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