~ubuntu-branches/ubuntu/saucy/sane-backends/saucy

« back to all changes in this revision

Viewing changes to backend/kvs20xx_opt.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2011-02-14 14:28:56 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110214142856-6gxjetg88q9zctid
Tags: 1.0.22-0ubuntu1
* New upstream release
* debian/control:
  - Use standards version 3.9.1
* debian/patches/allow_dll.d_symlinks.patch:
* debian/patches/fix_epson2_cancel.patch:
* debian/patches/fix_epson2_commands.patch:
* debian/patches/fix_xerox_mfp_color_mode.patch:
* debian/patches/genesys_disable_raw_data_log.patch:
* debian/patches/no_translations.patch:
* debian/patches/saned_exit_avahi_process.patch:
* debian/patches/scsi_perfection_2450.patch:
* debian/patches/scsi_scanjet_4c.patch:
* debian/patches/xerox_mfp_new_ids.patch:
  - Applied upstream
* debian/watch:
  - Dropped, the URL is not consistent between releases

Show diffs side-by-side

added added

removed removed

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