1 /*
2 Copyright (C) 2008, Panasonic Russia Ltd.
3 Copyright (C) 2010, m. allan noah
4 */
5 /*
6 Panasonic KV-S20xx USB-SCSI scanners.
7 */
8
9 #include "../include/sane/config.h"
10
11 #include <string.h>
12
13 #define DEBUG_DECLARE_ONLY
14 #define BACKEND_NAME kvs20xx
15
16 #include "../include/sane/sane.h"
17 #include "../include/sane/saneopts.h"
18 #include "../include/sane/sanei.h"
19 #include "../include/sane/sanei_backend.h"
20 #include "../include/sane/sanei_config.h"
21 #include "../include/lassert.h"
22
23 #include "kvs20xx.h"
24 #include "kvs20xx_cmd.h"
25
26 #include <stdlib.h>
27
28 static size_t
max_string_size(SANE_String_Const strings[])29 max_string_size (SANE_String_Const strings[])
30 {
31 size_t size, max_size = 0;
32 SANE_Int i;
33
34 for (i = 0; strings[i]; ++i)
35 {
36 size = strlen (strings[i]) + 1;
37 if (size > max_size)
38 max_size = size;
39 }
40 return max_size;
41 }
42 static SANE_String_Const mode_list[] = {
43 SANE_VALUE_SCAN_MODE_LINEART,
44 SANE_VALUE_SCAN_MODE_GRAY,
45 SANE_VALUE_SCAN_MODE_COLOR,
46 NULL
47 };
48 static const unsigned mode_val[] = { 0, 2, 5 };
49 static const unsigned bps_val[] = { 1, 8, 24 };
50
51 static const SANE_Range resolutions_range = {100,600,10};
52
53 /* List of feeder modes */
54 static SANE_String_Const feeder_mode_list[] = {
55 SANE_I18N ("single"),
56 SANE_I18N ("continuous"),
57 NULL
58 };
59
60 /* List of manual feed mode */
61 static SANE_String_Const manual_feed_list[] = {
62 SANE_I18N ("off"),
63 SANE_I18N ("wait_doc"),
64 SANE_I18N ("wait_key"),
65 NULL
66 };
67
68 /* List of paper sizes */
69 static SANE_String_Const paper_list[] = {
70 SANE_I18N ("user_def"),
71 SANE_I18N ("business_card"),
72 /*SANE_I18N("Check"), */
73 /*SANE_I18N ("A3"), */
74 SANE_I18N ("A4"),
75 SANE_I18N ("A5"),
76 SANE_I18N ("A6"),
77 SANE_I18N ("Letter"),
78 /*SANE_I18N ("Double letter 11x17 in"),
79 SANE_I18N ("B4"), */
80 SANE_I18N ("B5"),
81 SANE_I18N ("B6"),
82 SANE_I18N ("Legal"),
83 NULL
84 };
85 static const unsigned paper_val[] = { 0, 1, 4, 5, 6, 7, 13, 14, 15 };
86 struct paper_size
87 {
88 int width;
89 int height;
90 };
91 static const struct paper_size paper_sizes[] = {
92 {210, 297}, /* User defined, default=A4 */
93 {54, 90}, /* Business card */
94 /*{80, 170}, *//* Check (China business) */
95 /*{297, 420}, *//* A3 */
96 {210, 297}, /* A4 */
97 {148, 210}, /* A5 */
98 {105, 148}, /* A6 */
99 {215, 280}, /* US Letter 8.5 x 11 in */
100 /*{280, 432}, *//* Double Letter 11 x 17 in */
101 /*{250, 353}, *//* B4 */
102 {176, 250}, /* B5 */
103 {125, 176}, /* B6 */
104 {215, 355} /* US Legal */
105 };
106
107 #define MIN_WIDTH 51
108 #define MAX_WIDTH 215
109 #define MIN_LENGTH 70
110 #define MAX_LENGTH 355
111 static SANE_Range tl_x_range = { 0, MAX_WIDTH - MIN_WIDTH, 0 };
112 static SANE_Range tl_y_range = { 0, MAX_LENGTH - MIN_LENGTH, 0 };
113 static SANE_Range br_x_range = { MIN_WIDTH, MAX_WIDTH, 0 };
114 static SANE_Range br_y_range = { MIN_LENGTH, MAX_LENGTH, 0 };
115 static SANE_Range byte_value_range = { 0, 255, 0 };
116
117 /* List of image emphasis options, 5 steps */
118 static SANE_String_Const image_emphasis_list[] = {
119 SANE_I18N ("none"),
120 SANE_I18N ("low"),
121 SANE_I18N ("medium"),
122 SANE_I18N ("high"),
123 SANE_I18N ("smooth"),
124 NULL
125 };
126
127 /* List of gamma */
128 static SANE_String_Const gamma_list[] = {
129 SANE_I18N ("normal"),
130 SANE_I18N ("crt"),
131 NULL
132 };
133 static unsigned gamma_val[] = { 0, 1 };
134
135 /* List of lamp color dropout */
136 static SANE_String_Const lamp_list[] = {
137 SANE_I18N ("normal"),
138 SANE_I18N ("red"),
139 SANE_I18N ("green"),
140 SANE_I18N ("blue"),
141 NULL
142 };
143
144 /* Reset the options for that scanner. */
145 void
kvs20xx_init_options(struct scanner *s)146 kvs20xx_init_options (struct scanner *s)
147 {
148 int i;
149 SANE_Option_Descriptor *o;
150 /* Pre-initialize the options. */
151 memset (s->opt, 0, sizeof (s->opt));
152 memset (s->val, 0, sizeof (s->val));
153
154 for (i = 0; i < NUM_OPTIONS; i++)
155 {
156 s->opt[i].size = sizeof (SANE_Word);
157 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
158 }
159
160 /* Number of options. */
161 o = &s->opt[NUM_OPTS];
162 o->name = "";
163 o->title = SANE_TITLE_NUM_OPTIONS;
164 o->desc = SANE_DESC_NUM_OPTIONS;
165 o->type = SANE_TYPE_INT;
166 o->cap = SANE_CAP_SOFT_DETECT;
167 s->val[NUM_OPTS].w = NUM_OPTIONS;
168
169 /* Mode group */
170 o = &s->opt[MODE_GROUP];
171 o->title = SANE_I18N ("Scan Mode");
172 o->desc = ""; /* not valid for a group */
173 o->type = SANE_TYPE_GROUP;
174 o->cap = 0;
175 o->size = 0;
176 o->constraint_type = SANE_CONSTRAINT_NONE;
177
178 /* Scanner supported modes */
179 o = &s->opt[MODE];
180 o->name = SANE_NAME_SCAN_MODE;
181 o->title = SANE_TITLE_SCAN_MODE;
182 o->desc = SANE_DESC_SCAN_MODE;
183 o->type = SANE_TYPE_STRING;
184 o->size = max_string_size (mode_list);
185 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
186 o->constraint.string_list = mode_list;
187 s->val[MODE].s = malloc (o->size);
188 strcpy (s->val[MODE].s, mode_list[0]);
189
190 /* X and Y resolution */
191 o = &s->opt[RESOLUTION];
192 o->name = SANE_NAME_SCAN_RESOLUTION;
193 o->title = SANE_TITLE_SCAN_RESOLUTION;
194 o->desc = SANE_DESC_SCAN_RESOLUTION;
195 o->type = SANE_TYPE_INT;
196 o->unit = SANE_UNIT_DPI;
197 o->constraint_type = SANE_CONSTRAINT_RANGE;
198 o->constraint.range = &resolutions_range;
199 s->val[RESOLUTION].w = 100;
200
201 /* Duplex */
202 o = &s->opt[DUPLEX];
203 o->name = "duplex";
204 o->title = SANE_I18N ("Duplex");
205 o->desc = SANE_I18N ("Enable Duplex (Dual-Sided) Scanning");
206 o->type = SANE_TYPE_BOOL;
207 o->unit = SANE_UNIT_NONE;
208 s->val[DUPLEX].w = SANE_FALSE;
209
210 /*FIXME
211 if (!s->support_info.support_duplex)
212 o->cap |= SANE_CAP_INACTIVE;
213 */
214
215 /* Feeder mode */
216 o = &s->opt[FEEDER_MODE];
217 o->name = "feeder-mode";
218 o->title = SANE_I18N ("Feeder mode");
219 o->desc = SANE_I18N ("Sets the feeding mode");
220 o->type = SANE_TYPE_STRING;
221 o->size = max_string_size (feeder_mode_list);
222 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
223 o->constraint.string_list = feeder_mode_list;
224 s->val[FEEDER_MODE].s = malloc (o->size);
225 strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]);
226
227 /* Length control */
228 o = &s->opt[LENGTHCTL];
229 o->name = "length-control";
230 o->title = SANE_I18N ("Length control mode");
231 o->desc =
232 SANE_I18N
233 ("Length Control Mode causes the scanner to read the shorter of either the length of the actual"
234 " paper or logical document length.");
235 o->type = SANE_TYPE_BOOL;
236 o->unit = SANE_UNIT_NONE;
237 s->val[LENGTHCTL].w = SANE_FALSE;
238
239 /* Manual feed */
240 o = &s->opt[MANUALFEED];
241 o->name = "manual-feed";
242 o->title = SANE_I18N ("Manual feed mode");
243 o->desc = SANE_I18N ("Sets the manual feed mode");
244 o->type = SANE_TYPE_STRING;
245 o->size = max_string_size (manual_feed_list);
246 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
247 o->constraint.string_list = manual_feed_list;
248 s->val[MANUALFEED].s = malloc (o->size);
249 strcpy (s->val[MANUALFEED].s, manual_feed_list[0]);
250
251 /*Manual feed timeout */
252 o = &s->opt[FEED_TIMEOUT];
253 o->name = "feed-timeout";
254 o->title = SANE_I18N ("Manual feed timeout");
255 o->desc = SANE_I18N ("Sets the manual feed timeout in seconds");
256 o->type = SANE_TYPE_INT;
257 o->unit = SANE_UNIT_NONE;
258 o->size = sizeof (SANE_Int);
259 o->constraint_type = SANE_CONSTRAINT_RANGE;
260 o->constraint.range = &(byte_value_range);
261 o->cap |= SANE_CAP_INACTIVE;
262 s->val[FEED_TIMEOUT].w = 30;
263
264 /* Double feed */
265 o = &s->opt[DBLFEED];
266 o->name = "double-feed";
267 o->title = SANE_I18N ("Double feed detection");
268 o->desc = SANE_I18N ("Enable/Disable double feed detection");
269 o->type = SANE_TYPE_BOOL;
270 o->unit = SANE_UNIT_NONE;
271 s->val[DBLFEED].w = SANE_FALSE;
272
273
274 /* Fit to page */
275 o = &s->opt[FIT_TO_PAGE];
276 o->name = SANE_I18N ("fit-to-page");
277 o->title = SANE_I18N ("Fit to page");
278 o->desc = SANE_I18N ("Scanner shrinks image to fit scanned page");
279 o->type = SANE_TYPE_BOOL;
280 o->unit = SANE_UNIT_NONE;
281 s->val[FIT_TO_PAGE].w = SANE_FALSE;
282
283 /* Geometry group */
284 o = &s->opt[GEOMETRY_GROUP];
285 o->title = SANE_I18N ("Geometry");
286 o->desc = ""; /* not valid for a group */
287 o->type = SANE_TYPE_GROUP;
288 o->cap = 0;
289 o->size = 0;
290 o->constraint_type = SANE_CONSTRAINT_NONE;
291
292 /* Paper sizes list */
293 o = &s->opt[PAPER_SIZE];
294 o->name = "paper-size";
295 o->title = SANE_I18N ("Paper size");
296 o->desc = SANE_I18N ("Physical size of the paper in the ADF");
297 o->type = SANE_TYPE_STRING;
298 o->size = max_string_size (paper_list);
299 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
300 o->constraint.string_list = paper_list;
301 s->val[PAPER_SIZE].s = malloc (o->size);
302 strcpy (s->val[PAPER_SIZE].s, SANE_I18N ("A4"));
303
304 /* Landscape */
305 o = &s->opt[LANDSCAPE];
306 o->name = "landscape";
307 o->title = SANE_I18N ("Landscape");
308 o->desc =
309 SANE_I18N ("Set paper position : "
310 "true for landscape, false for portrait");
311 o->type = SANE_TYPE_BOOL;
312 o->unit = SANE_UNIT_NONE;
313 s->val[LANDSCAPE].w = SANE_FALSE;
314 o->cap |= SANE_CAP_INACTIVE;
315
316 /* Upper left X */
317 o = &s->opt[TL_X];
318 o->name = SANE_NAME_SCAN_TL_X;
319 o->title = SANE_TITLE_SCAN_TL_X;
320 o->desc = SANE_DESC_SCAN_TL_X;
321 o->type = SANE_TYPE_INT;
322 o->unit = SANE_UNIT_MM;
323 o->constraint_type = SANE_CONSTRAINT_RANGE;
324 o->constraint.range = &tl_x_range;
325 o->cap |= SANE_CAP_INACTIVE;
326 s->val[TL_X].w = 0;
327
328 /* Upper left Y */
329 o = &s->opt[TL_Y];
330 o->name = SANE_NAME_SCAN_TL_Y;
331 o->title = SANE_TITLE_SCAN_TL_Y;
332 o->desc = SANE_DESC_SCAN_TL_Y;
333 o->type = SANE_TYPE_INT;
334 o->unit = SANE_UNIT_MM;
335 o->constraint_type = SANE_CONSTRAINT_RANGE;
336 o->constraint.range = &tl_y_range;
337 o->cap |= SANE_CAP_INACTIVE;
338 s->val[TL_Y].w = 0;
339
340 /* Bottom-right x */
341 o = &s->opt[BR_X];
342 o->name = SANE_NAME_SCAN_BR_X;
343 o->title = SANE_TITLE_SCAN_BR_X;
344 o->desc = SANE_DESC_SCAN_BR_X;
345 o->type = SANE_TYPE_INT;
346 o->unit = SANE_UNIT_MM;
347 o->constraint_type = SANE_CONSTRAINT_RANGE;
348 o->constraint.range = &br_x_range;
349 o->cap |= SANE_CAP_INACTIVE;
350 s->val[BR_X].w = 210;
351
352 /* Bottom-right y */
353 o = &s->opt[BR_Y];
354 o->name = SANE_NAME_SCAN_BR_Y;
355 o->title = SANE_TITLE_SCAN_BR_Y;
356 o->desc = SANE_DESC_SCAN_BR_Y;
357 o->type = SANE_TYPE_INT;
358 o->unit = SANE_UNIT_MM;
359 o->constraint_type = SANE_CONSTRAINT_RANGE;
360 o->constraint.range = &br_y_range;
361 o->cap |= SANE_CAP_INACTIVE;
362 s->val[BR_Y].w = 297;
363
364 /* Enhancement group */
365 o = &s->opt[ADVANCED_GROUP];
366 o->title = SANE_I18N ("Advanced");
367 o->desc = ""; /* not valid for a group */
368 o->type = SANE_TYPE_GROUP;
369 o->cap = SANE_CAP_ADVANCED;
370 o->size = 0;
371 o->constraint_type = SANE_CONSTRAINT_NONE;
372
373 /* Brightness */
374 o = &s->opt[BRIGHTNESS];
375 o->name = SANE_NAME_BRIGHTNESS;
376 o->title = SANE_TITLE_BRIGHTNESS;
377 o->desc = SANE_DESC_BRIGHTNESS;
378 o->type = SANE_TYPE_INT;
379 o->unit = SANE_UNIT_NONE;
380 o->size = sizeof (SANE_Int);
381 o->constraint_type = SANE_CONSTRAINT_RANGE;
382 o->constraint.range = &(byte_value_range);
383 s->val[BRIGHTNESS].w = 128;
384
385 /* Contrast */
386 o = &s->opt[CONTRAST];
387 o->name = SANE_NAME_CONTRAST;
388 o->title = SANE_TITLE_CONTRAST;
389 o->desc = SANE_DESC_CONTRAST;
390 o->type = SANE_TYPE_INT;
391 o->unit = SANE_UNIT_NONE;
392 o->size = sizeof (SANE_Int);
393 o->constraint_type = SANE_CONSTRAINT_RANGE;
394 o->constraint.range = &(byte_value_range);
395 s->val[CONTRAST].w = 128;
396
397 /* threshold */
398 o = &s->opt[THRESHOLD];
399 o->name = SANE_NAME_THRESHOLD;
400 o->title = SANE_TITLE_THRESHOLD;
401 o->desc = SANE_DESC_THRESHOLD;
402 o->type = SANE_TYPE_INT;
403 o->size = sizeof (SANE_Int);
404 o->constraint_type = SANE_CONSTRAINT_RANGE;
405 o->constraint.range = &(byte_value_range);
406 s->val[THRESHOLD].w = 128;
407
408
409 /* Image emphasis */
410 o = &s->opt[IMAGE_EMPHASIS];
411 o->name = "image-emphasis";
412 o->title = SANE_I18N ("Image emphasis");
413 o->desc = SANE_I18N ("Sets the image emphasis");
414 o->type = SANE_TYPE_STRING;
415 o->size = max_string_size (image_emphasis_list);
416 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
417 o->constraint.string_list = image_emphasis_list;
418 s->val[IMAGE_EMPHASIS].s = malloc (o->size);
419 strcpy (s->val[IMAGE_EMPHASIS].s, image_emphasis_list[0]);
420
421 /* Gamma */
422 o = &s->opt[GAMMA_CORRECTION];
423 o->name = "gamma-cor";
424 o->title = SANE_I18N ("Gamma correction");
425 o->desc = SANE_I18N ("Gamma correction");
426 o->type = SANE_TYPE_STRING;
427 o->size = max_string_size (gamma_list);
428 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
429 o->constraint.string_list = gamma_list;
430 s->val[GAMMA_CORRECTION].s = malloc (o->size);
431 strcpy (s->val[GAMMA_CORRECTION].s, gamma_list[0]);
432
433 /* Lamp color dropout */
434 o = &s->opt[LAMP];
435 o->name = "lamp-color";
436 o->title = SANE_I18N ("Lamp color");
437 o->desc = SANE_I18N ("Sets the lamp color (color dropout)");
438 o->type = SANE_TYPE_STRING;
439 o->size = max_string_size (lamp_list);
440 o->constraint_type = SANE_CONSTRAINT_STRING_LIST;
441 o->constraint.string_list = lamp_list;
442 s->val[LAMP].s = malloc (o->size);
443 strcpy (s->val[LAMP].s, lamp_list[0]);
444
445 }
446
447 /* Lookup a string list from one array and return its index. */
448 static int
str_index(const SANE_String_Const * list, SANE_String_Const name)449 str_index (const SANE_String_Const * list, SANE_String_Const name)
450 {
451 int index;
452 index = 0;
453 while (list[index])
454 {
455 if (!strcmp (list[index], name))
456 return (index);
457 index++;
458 }
459 return (-1); /* not found */
460 }
461
462 /* Control option */
463 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)464 sane_control_option (SANE_Handle handle, SANE_Int option,
465 SANE_Action action, void *val, SANE_Int * info)
466 {
467 int i;
468 SANE_Status status;
469 SANE_Word cap;
470 struct scanner *s = (struct scanner *) handle;
471
472 if (info)
473 *info = 0;
474
475 if (option < 0 || option >= NUM_OPTIONS)
476 return SANE_STATUS_UNSUPPORTED;
477
478 cap = s->opt[option].cap;
479 if (!SANE_OPTION_IS_ACTIVE (cap))
480 return SANE_STATUS_UNSUPPORTED;
481
482 if (action == SANE_ACTION_GET_VALUE)
483 {
484 if (s->opt[option].type == SANE_TYPE_STRING)
485 {
486 DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %s\n",
487 option, s->val[option].s);
488 strcpy (val, s->val[option].s);
489 }
490 else
491 {
492 *(SANE_Word *) val = s->val[option].w;
493 DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %d\n",
494 option, s->val[option].w);
495 }
496 return SANE_STATUS_GOOD;
497
498 }
499 else if (action == SANE_ACTION_SET_VALUE)
500 {
501 if (!SANE_OPTION_IS_SETTABLE (cap))
502 return SANE_STATUS_INVAL;
503
504 status = sanei_constrain_value (s->opt + option, val, info);
505 if (status != SANE_STATUS_GOOD)
506 return status;
507
508 if (s->opt[option].type == SANE_TYPE_STRING)
509 {
510 if (!strcmp (val, s->val[option].s))
511 return SANE_STATUS_GOOD;
512 DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %s\n",
513 option, (SANE_String_Const) val);
514 }
515 else
516 {
517 if (*(SANE_Word *) val == s->val[option].w)
518 return SANE_STATUS_GOOD;
519 DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %d\n",
520 option, *(SANE_Word *) val);
521 }
522
523 switch (option)
524 {
525 /* Side-effect options */
526 case RESOLUTION:
527 s->val[option].w = *(SANE_Word *) val;
528 if (info)
529 *info |= SANE_INFO_RELOAD_PARAMS;
530 return SANE_STATUS_GOOD;
531
532 case TL_Y:
533 if ((*(SANE_Word *) val) + MIN_LENGTH <= s->val[BR_Y].w)
534 {
535 s->val[option].w = *(SANE_Word *) val;
536 if (info)
537 *info |= SANE_INFO_RELOAD_PARAMS;
538 }
539 else if (info)
540 *info |= SANE_INFO_INEXACT;
541 return SANE_STATUS_GOOD;
542 case BR_Y:
543 if ((*(SANE_Word *) val) >= s->val[TL_Y].w + MIN_LENGTH)
544 {
545 s->val[option].w = *(SANE_Word *) val;
546 if (info)
547 *info |= SANE_INFO_RELOAD_PARAMS;
548 }
549 else if (info)
550 *info |= SANE_INFO_INEXACT;
551 return SANE_STATUS_GOOD;
552
553 case TL_X:
554 if ((*(SANE_Word *) val) + MIN_WIDTH <= s->val[BR_X].w)
555 {
556 s->val[option].w = *(SANE_Word *) val;
557 if (info)
558 *info |= SANE_INFO_RELOAD_PARAMS;
559 }
560 else if (info)
561 *info |= SANE_INFO_INEXACT;
562 return SANE_STATUS_GOOD;
563
564 case BR_X:
565 if (*(SANE_Word *) val >= s->val[TL_X].w + MIN_WIDTH)
566 {
567 s->val[option].w = *(SANE_Word *) val;
568 if (info)
569 *info |= SANE_INFO_RELOAD_PARAMS;
570 }
571 else if (info)
572 *info |= SANE_INFO_INEXACT;
573 return SANE_STATUS_GOOD;
574
575 case LANDSCAPE:
576 s->val[option].w = *(SANE_Word *) val;
577 if (info)
578 *info |= SANE_INFO_RELOAD_PARAMS;
579 return SANE_STATUS_GOOD;
580
581 /* Side-effect free options */
582 case CONTRAST:
583 case BRIGHTNESS:
584 case DUPLEX:
585 case LENGTHCTL:
586 case DBLFEED:
587 case FIT_TO_PAGE:
588 case THRESHOLD:
589 s->val[option].w = *(SANE_Word *) val;
590 return SANE_STATUS_GOOD;
591
592 case FEED_TIMEOUT:
593 s->val[option].w = *(SANE_Word *) val;
594 return kvs20xx_set_timeout (s, s->val[option].w);
595
596 /* String mode */
597 case IMAGE_EMPHASIS:
598 case GAMMA_CORRECTION:
599 case LAMP:
600 case FEEDER_MODE:
601 strcpy (s->val[option].s, val);
602 return SANE_STATUS_GOOD;
603
604 case MODE:
605 strcpy (s->val[MODE].s, val);
606 if (!strcmp (s->val[MODE].s, SANE_VALUE_SCAN_MODE_LINEART))
607 {
608 s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
609 s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
610 s->opt[BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
611 }
612 else
613 {
614 s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE;
615 s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE;
616 s->opt[BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
617 }
618 if (info)
619 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
620
621 return SANE_STATUS_GOOD;
622
623 case MANUALFEED:
624 strcpy (s->val[option].s, val);
625 if (strcmp (s->val[option].s, manual_feed_list[0]) == 0) /* off */
626 s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE;
627 else
628 s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE;
629 if (info)
630 *info |= SANE_INFO_RELOAD_OPTIONS;
631
632 return SANE_STATUS_GOOD;
633
634 case PAPER_SIZE:
635 strcpy (s->val[PAPER_SIZE].s, val);
636 i = str_index (paper_list, s->val[PAPER_SIZE].s);
637 if (i == 0)
638 { /*user def */
639 s->opt[TL_X].cap &=
640 s->opt[TL_Y].cap &=
641 s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE;
642 s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
643 s->val[LANDSCAPE].w = 0;
644 }
645 else
646 {
647 s->opt[TL_X].cap |=
648 s->opt[TL_Y].cap |=
649 s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE;
650 if (i == 3 || i == 4 || i == 7)
651 { /*A5, A6 or B6 */
652 s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE;
653 }
654 else
655 {
656 s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE;
657 s->val[LANDSCAPE].w = 0;
658 }
659 }
660 if (info)
661 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
662
663 return SANE_STATUS_GOOD;
664 }
665 }
666
667
668 return SANE_STATUS_UNSUPPORTED;
669 }
670
671 static inline unsigned
mm2scanner_units(unsigned mm)672 mm2scanner_units (unsigned mm)
673 {
674 return mm * 12000 / 254;
675 }
676
677 void
kvs20xx_init_window(struct scanner *s, struct window *wnd, int wnd_id)678 kvs20xx_init_window (struct scanner *s, struct window *wnd, int wnd_id)
679 {
680 int paper = str_index (paper_list, s->val[PAPER_SIZE].s);
681 memset (wnd, 0, sizeof (struct window));
682 wnd->window_descriptor_block_length = cpu2be16 (64);
683
684 wnd->window_identifier = wnd_id;
685 wnd->x_resolution = cpu2be16 (s->val[RESOLUTION].w);
686 wnd->y_resolution = cpu2be16 (s->val[RESOLUTION].w);
687 if (!paper)
688 {
689 wnd->upper_left_x =
690 cpu2be32 (mm2scanner_units (s->val[TL_X].w));
691 wnd->upper_left_y =
692 cpu2be32 (mm2scanner_units (s->val[TL_Y].w));
693 wnd->width =
694 cpu2be32 (mm2scanner_units (s->val[BR_X].w - s->val[TL_X].w));
695 wnd->length =
696 cpu2be32 (mm2scanner_units (s->val[BR_Y].w - s->val[TL_Y].w));
697 }
698 else
699 {
700 u32 w = cpu2be32 (mm2scanner_units (paper_sizes[paper].width));
701 u32 h = cpu2be32 (mm2scanner_units (paper_sizes[paper].height));
702 wnd->upper_left_x = cpu2be32 (mm2scanner_units (0));
703 wnd->upper_left_y = cpu2be32 (mm2scanner_units (0));
704 if (!s->val[LANDSCAPE].b)
705 {
706 wnd->document_width = wnd->width = w;
707 wnd->document_length = wnd->length = h;
708 }
709 else
710 {
711 wnd->document_width = wnd->width = h;
712 wnd->document_length = wnd->length = w;
713 }
714 }
715 wnd->brightness = s->val[BRIGHTNESS].w;
716 wnd->threshold = s->val[THRESHOLD].w;
717 wnd->contrast = s->val[CONTRAST].w;
718 wnd->image_composition = mode_val[str_index (mode_list, s->val[MODE].s)];
719 wnd->bit_per_pixel = bps_val[str_index (mode_list, s->val[MODE].s)];
720 wnd->halftone_pattern = 0; /*Does not supported */
721 wnd->bit_ordering = cpu2be16 (BIT_ORDERING);
722 wnd->compression_type = 0; /*Does not supported */
723 wnd->compression_argument = 0; /*Does not supported */
724
725 wnd->vendor_unique_identifier = 0;
726 wnd->nobuf_fstspeed_dfstop = 0;
727 wnd->mirror_image = 0;
728 wnd->image_emphasis = str_index (image_emphasis_list,
729 s->val[IMAGE_EMPHASIS].s);
730 wnd->gamma_correction = gamma_val[str_index (gamma_list,
731 s->val[GAMMA_CORRECTION].s)];
732 wnd->mcd_lamp_dfeed_sens = str_index (lamp_list, s->val[LAMP].s) << 4 | 2;
733
734 wnd->document_size = ((paper != 0) << 7) | (s->val[LENGTHCTL].b << 6)
735 | (s->val[LANDSCAPE].b << 4) | paper_val[paper];
736
737 wnd->ahead_deskew_dfeed_scan_area_fspeed_rshad = s->val[DBLFEED].b << 4
738 | s->val[FIT_TO_PAGE].b << 2;
739 wnd->continuous_scanning_pages = str_index (feeder_mode_list,
740 s->val[FEEDER_MODE].
741 s) ? 0xff : 0;
742 wnd->automatic_threshold_mode = 0; /*Does not supported */
743 wnd->automatic_separation_mode = 0; /*Does not supported */
744 wnd->standard_white_level_mode = 0; /*Does not supported */
745 wnd->b_wnr_noise_reduction = 0; /*Does not supported */
746 if (str_index (manual_feed_list, s->val[MANUALFEED].s) == 2)
747 wnd->mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr = 2 << 6;
748
749 wnd->stop_mode = 1;
750 }
751
752
753 /* Get scan parameters */
754 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)755 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
756 {
757 struct scanner *s = (struct scanner *) handle;
758 SANE_Parameters *p = &s->params;
759
760 if (!s->scanning)
761 {
762 unsigned w, h, res = s->val[RESOLUTION].w;
763 unsigned i = str_index (paper_list,
764 s->val[PAPER_SIZE].s);
765 if (i)
766 {
767 if (s->val[LANDSCAPE].b)
768 {
769 w = paper_sizes[i].height;
770 h = paper_sizes[i].width;
771 }
772 else
773 {
774 w = paper_sizes[i].width;
775 h = paper_sizes[i].height;
776 }
777 }
778 else
779 {
780 w = s->val[BR_X].w - s->val[TL_X].w;
781 h = s->val[BR_Y].w - s->val[TL_Y].w;
782 }
783 p->pixels_per_line = w * res / 25.4;
784 p->lines = h * res / 25.4;
785 }
786
787 p->format = (!strcmp(s->val[MODE].s,SANE_VALUE_SCAN_MODE_COLOR)) ?
788 SANE_FRAME_RGB : SANE_FRAME_GRAY;
789 p->last_frame = SANE_TRUE;
790 p->depth = bps_val[str_index (mode_list, s->val[MODE].s)];
791 p->bytes_per_line = p->depth * p->pixels_per_line / 8;
792 if (p->depth > 8)
793 p->depth = 8;
794 if (params)
795 memcpy (params, p, sizeof (SANE_Parameters));
796 return SANE_STATUS_GOOD;
797 }
798