~ubuntu-branches/debian/jessie/sane-backends/jessie

« back to all changes in this revision

Viewing changes to backend/kvs40xx_opt.c

  • Committer: Package Import Robot
  • Author(s): Markus Koschany
  • Date: 2013-07-04 17:41:47 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20130704174147-tl5tzd8bwvmctka2
Tags: 1.0.23-1
* QA upload.
* New upstream release.
* This package has been orphaned. Set maintainer to the Debian QA Group.
* Bump compat level to 9 (was 5) and require debhelper >= 9.
* debian/control:
  - sane-utils: Inherit Section: graphics from source package sane-backends.
  - Remove versioned dependencies. They are trivially satisfied.
* Drop the following patches. They are merged upstream now.
  - fix_v4l_build.patch
  - hurd_path_max_fix.patch
  - sane_desc_udev+acl.patch
  - scanimage_man_batch_start.patch
  - udev_usb_suspend.patch
  - xerox_mfp_add_scx_4623fw.patch
  - xerox_mfp_fix_usb_device.patch
* Drop disable_rpath.patch because the RPATH is already removed by chrpath
  in debian/rules.
* Rebase and refresh all other patches against the new upstream relase.
* debian/rules:
  - Simplify debian/rules by using dh sequencer.
  - Build with --parallel and with autotools_dev.
  - Enable all hardening build flags.
  - Install umax_pp with sane-utils.install.
* Build-Depend on libtiff5-dev. Thanks to Michael Terry for the patch.
  (Closes: #681079)
* Build-Depend on libusb-1.0-0-dev and enable libusb1.0 support in
  debian/rules. Thanks to Martin Pitt for the report and Whoopie for the
  patch. (Closes: #687137)

Show diffs side-by-side

added added

removed removed

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