xref: /third_party/backends/backend/test.c (revision 141cc406)
1/* sane - Scanner Access Now Easy.
2
3   Copyright (C) 2002-2006 Henning Meier-Geinitz <henning@meier-geinitz.de>
4   Changes according to the sanei_thread usage by
5                                         Gerhard Jaeger <gerhard@gjaeger.de>
6
7   This file is part of the SANE package.
8
9   This program is free software; you can redistribute it and/or
10   modify it under the terms of the GNU General Public License as
11   published by the Free Software Foundation; either version 2 of the
12   License, or (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
22   As a special exception, the authors of SANE give permission for
23   additional uses of the libraries contained in this release of SANE.
24
25   The exception is that, if you link a SANE library with other files
26   to produce an executable, this does not by itself cause the
27   resulting executable to be covered by the GNU General Public
28   License.  Your use of that executable is in no way restricted on
29   account of linking the SANE library code into it.
30
31   This exception does not, however, invalidate any other reasons why
32   the executable file might be covered by the GNU General Public
33   License.
34
35   If you submit changes to SANE to the maintainers to be included in
36   a subsequent release, you agree by submitting the changes that
37   those changes may be distributed with this exception intact.
38
39   If you write modifications of your own for SANE, it is your choice
40   whether to permit this exception to apply to your modifications.
41   If you do not wish that, delete this exception notice.
42
43   This backend is for testing frontends.
44*/
45
46#define BUILD 28
47
48#include "../include/sane/config.h"
49
50#include <errno.h>
51#include <signal.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <sys/types.h>
56#include <time.h>
57#include <unistd.h>
58#include <fcntl.h>
59
60#include "../include/_stdint.h"
61
62#include "../include/sane/sane.h"
63#include "../include/sane/sanei.h"
64#include "../include/sane/saneopts.h"
65#include "../include/sane/sanei_config.h"
66#include "../include/sane/sanei_thread.h"
67
68#define BACKEND_NAME	test
69#include "../include/sane/sanei_backend.h"
70
71#include "test.h"
72
73#include "test-picture.c"
74
75#define TEST_CONFIG_FILE "test.conf"
76
77static SANE_Bool inited = SANE_FALSE;
78static SANE_Device **sane_device_list = 0;
79static Test_Device *first_test_device = 0;
80
81static SANE_Range geometry_range = {
82  SANE_FIX (0.0),
83  SANE_FIX (200.0),
84  SANE_FIX (1.0)
85};
86
87static SANE_Range resolution_range = {
88  SANE_FIX (1.0),
89  SANE_FIX (1200.0),
90  SANE_FIX (1.0)
91};
92
93static SANE_Range ppl_loss_range = {
94  0,
95  128,
96  1
97};
98
99static SANE_Range read_limit_size_range = {
100  1,
101  64 * 1024,			/* 64 KB ought to be enough for everyone :-) */
102  1
103};
104
105static SANE_Range read_delay_duration_range = {
106  1000,
107  200 * 1000,			/* 200 msec */
108  1000
109};
110
111static SANE_Range int_constraint_range = {
112  4,
113  192,
114  2
115};
116
117static SANE_Range gamma_range = {
118  0,
119  255,
120  1
121};
122
123static SANE_Range fixed_constraint_range = {
124  SANE_FIX (-42.17),
125  SANE_FIX (32767.9999),
126  SANE_FIX (2.0)
127};
128
129static SANE_String_Const mode_list[] = {
130  SANE_VALUE_SCAN_MODE_GRAY,
131  SANE_VALUE_SCAN_MODE_COLOR,
132  0
133};
134
135static SANE_String_Const order_list[] = {
136  "RGB", "RBG", "GBR", "GRB", "BRG", "BGR",
137  0
138};
139
140static SANE_String_Const test_picture_list[] = {
141  SANE_I18N ("Solid black"), SANE_I18N ("Solid white"),
142  SANE_I18N ("Color pattern"), SANE_I18N ("Grid"),
143  0
144};
145
146static SANE_String_Const read_status_code_list[] = {
147  SANE_I18N ("Default"), "SANE_STATUS_UNSUPPORTED", "SANE_STATUS_CANCELLED",
148  "SANE_STATUS_DEVICE_BUSY", "SANE_STATUS_INVAL", "SANE_STATUS_EOF",
149  "SANE_STATUS_JAMMED", "SANE_STATUS_NO_DOCS", "SANE_STATUS_COVER_OPEN",
150  "SANE_STATUS_IO_ERROR", "SANE_STATUS_NO_MEM", "SANE_STATUS_ACCESS_DENIED",
151  0
152};
153
154static SANE_Int depth_list[] = {
155  3, 1, 8, 16
156};
157
158static SANE_Int int_constraint_word_list[] = {
159  9, -42, -8, 0, 17, 42, 256, 65536, 256 * 256 * 256, 256 * 256 * 256 * 64
160};
161
162static SANE_Int fixed_constraint_word_list[] = {
163  4, SANE_FIX (-32.7), SANE_FIX (12.1), SANE_FIX (42.0), SANE_FIX (129.5)
164};
165
166static SANE_String_Const string_constraint_string_list[] = {
167  SANE_I18N ("First entry"), SANE_I18N ("Second entry"),
168  SANE_I18N
169    ("This is the very long third entry. Maybe the frontend has an idea how to "
170     "display it"),
171  0
172};
173
174static SANE_String_Const string_constraint_long_string_list[] = {
175  SANE_I18N ("First entry"), SANE_I18N ("Second entry"), "3", "4", "5", "6",
176  "7", "8", "9", "10",
177  "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
178  "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34",
179  "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46",
180  0
181};
182
183static SANE_Int int_array[] = {
184  -17, 0, -5, 42, 91, 256 * 256 * 256 * 64
185};
186
187static SANE_Int int_array_constraint_range[] = {
188  48, 6, 4, 92, 190, 16
189};
190
191#define GAMMA_RED_SIZE 256
192#define GAMMA_GREEN_SIZE 256
193#define GAMMA_BLUE_SIZE 256
194#define GAMMA_ALL_SIZE 4096
195static SANE_Int gamma_red[GAMMA_RED_SIZE]; // initialized in init_options()
196static SANE_Int gamma_green[GAMMA_GREEN_SIZE];
197static SANE_Int gamma_blue[GAMMA_BLUE_SIZE];
198static SANE_Int gamma_all[GAMMA_ALL_SIZE];
199
200static void
201init_gamma_table(SANE_Int *tablePtr, SANE_Int count, SANE_Int max)
202{
203  for (int i=0; i<count; ++i) {
204    tablePtr[i] = (SANE_Int)(((double)i * max)/(double)count);
205  }
206}
207
208static void
209print_gamma_table(SANE_Int *tablePtr, SANE_Int count)
210{
211  char str[200];
212  str[0] = '\0';
213  DBG (5, "Gamma Table Size: %d\n", count);
214  for (int i=0; i<count; ++i) {
215    if (i%16 == 0 && strlen(str) > 0) {
216      DBG (5, "%s\n", str);
217      str[0] = '\0';
218    }
219    sprintf (str + strlen(str), " %04X", tablePtr[i]);
220  }
221  if (strlen(str) > 0) {
222    DBG (5, "%s\n", str);
223  }
224}
225
226
227static SANE_Int int_array_constraint_word_list[] = {
228  -42, 0, -8, 17, 42, 42
229};
230
231static SANE_String_Const source_list[] = {
232  SANE_I18N ("Flatbed"), SANE_I18N ("Automatic Document Feeder"),
233  0
234};
235
236static double random_factor;	/* use for fuzzyness of parameters */
237
238/* initial values. Initial string values are set in sane_init() */
239static SANE_Word init_number_of_devices = 2;
240static SANE_Fixed init_tl_x = SANE_FIX (0.0);
241static SANE_Fixed init_tl_y = SANE_FIX (0.0);
242static SANE_Fixed init_br_x = SANE_FIX (80.0);
243static SANE_Fixed init_br_y = SANE_FIX (100.0);
244static SANE_Word init_resolution = 50;
245static SANE_String init_mode = NULL;
246static SANE_Word init_depth = 8;
247static SANE_Bool init_hand_scanner = SANE_FALSE;
248static SANE_Bool init_three_pass = SANE_FALSE;
249static SANE_String init_three_pass_order = NULL;
250static SANE_String init_scan_source = NULL;
251static SANE_String init_test_picture = NULL;
252static SANE_Bool init_invert_endianess = SANE_FALSE;
253static SANE_Bool init_read_limit = SANE_FALSE;
254static SANE_Word init_read_limit_size = 1;
255static SANE_Bool init_read_delay = SANE_FALSE;
256static SANE_Word init_read_delay_duration = 1000;
257static SANE_String init_read_status_code = NULL;
258static SANE_Bool init_fuzzy_parameters = SANE_FALSE;
259static SANE_Word init_ppl_loss = 0;
260static SANE_Bool init_non_blocking = SANE_FALSE;
261static SANE_Bool init_select_fd = SANE_FALSE;
262static SANE_Bool init_enable_test_options = SANE_FALSE;
263static SANE_String init_string = NULL;
264static SANE_String init_string_constraint_string_list = NULL;
265static SANE_String init_string_constraint_long_string_list = NULL;
266
267/* Test if this machine is little endian (from coolscan.c) */
268static SANE_Bool
269little_endian (void)
270{
271  SANE_Int testvalue = 255;
272  uint8_t *firstbyte = (uint8_t *) & testvalue;
273
274  if (*firstbyte == 255)
275    return SANE_TRUE;
276  return SANE_FALSE;
277}
278
279static void
280swap_double (double *a, double *b)
281{
282  double c;
283
284  c = *a;
285  *a = *b;
286  *b = c;
287
288  return;
289}
290
291static size_t
292max_string_size (const SANE_String_Const strings[])
293{
294  size_t size, max_size = 0;
295  SANE_Int i;
296
297  for (i = 0; strings[i]; ++i)
298    {
299      size = strlen (strings[i]) + 1;
300      if (size > max_size)
301	max_size = size;
302    }
303  return max_size;
304}
305
306static SANE_Bool
307check_handle (SANE_Handle handle)
308{
309  Test_Device *test_device = first_test_device;
310
311  while (test_device)
312    {
313      if (test_device == (Test_Device *) handle)
314	return SANE_TRUE;
315      test_device = test_device->next;
316    }
317  return SANE_FALSE;
318}
319
320static void
321cleanup_options (Test_Device * test_device)
322{
323  DBG (2, "cleanup_options: test_device=%p\n", (void *) test_device);
324
325  free(test_device->val[opt_mode].s);
326  test_device->val[opt_mode].s = NULL;
327
328  free(test_device->val[opt_three_pass_order].s);
329  test_device->val[opt_three_pass_order].s = NULL;
330
331  free(test_device->val[opt_scan_source].s);
332  test_device->val[opt_scan_source].s = NULL;
333
334  free(test_device->val[opt_test_picture].s);
335  test_device->val[opt_test_picture].s = NULL;
336
337  free(test_device->val[opt_read_status_code].s);
338  test_device->val[opt_read_status_code].s = NULL;
339
340  free(test_device->val[opt_string].s);
341  test_device->val[opt_string].s = NULL;
342
343  free(test_device->val[opt_string_constraint_string_list].s);
344  test_device->val[opt_string_constraint_string_list].s = NULL;
345
346  free(test_device->val[opt_string_constraint_long_string_list].s);
347  test_device->val[opt_string_constraint_long_string_list].s = NULL;
348
349  test_device->options_initialized = SANE_FALSE;
350}
351
352static SANE_Status
353init_options (Test_Device * test_device)
354{
355  SANE_Option_Descriptor *od;
356
357  DBG (2, "init_options: test_device=%p\n", (void *) test_device);
358
359  /* opt_num_opts */
360  od = &test_device->opt[opt_num_opts];
361  od->name = "";
362  od->title = SANE_TITLE_NUM_OPTIONS;
363  od->desc = SANE_DESC_NUM_OPTIONS;
364  od->type = SANE_TYPE_INT;
365  od->unit = SANE_UNIT_NONE;
366  od->size = sizeof (SANE_Word);
367  od->cap = SANE_CAP_SOFT_DETECT;
368  od->constraint_type = SANE_CONSTRAINT_NONE;
369  od->constraint.range = 0;
370  test_device->val[opt_num_opts].w = num_options;
371
372  test_device->loaded[opt_num_opts] = 1;
373
374  /* opt_mode_group */
375  od = &test_device->opt[opt_mode_group];
376  od->name = "";
377  od->title = SANE_I18N ("Scan Mode");
378  od->desc = "";
379  od->type = SANE_TYPE_GROUP;
380  od->unit = SANE_UNIT_NONE;
381  od->size = 0;
382  od->cap = 0;
383  od->constraint_type = SANE_CONSTRAINT_NONE;
384  od->constraint.range = 0;
385  test_device->val[opt_mode_group].w = 0;
386
387  /* opt_mode */
388  od = &test_device->opt[opt_mode];
389  od->name = SANE_NAME_SCAN_MODE;
390  od->title = SANE_TITLE_SCAN_MODE;
391  od->desc = SANE_DESC_SCAN_MODE;
392  od->type = SANE_TYPE_STRING;
393  od->unit = SANE_UNIT_NONE;
394  od->size = (SANE_Int) max_string_size (mode_list);
395  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
396  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
397  od->constraint.string_list = mode_list;
398  test_device->val[opt_mode].s = malloc ((size_t) od->size);
399  if (!test_device->val[opt_mode].s)
400    goto fail;
401  strcpy (test_device->val[opt_mode].s, init_mode);
402
403  /* opt_depth */
404  od = &test_device->opt[opt_depth];
405  od->name = SANE_NAME_BIT_DEPTH;
406  od->title = SANE_TITLE_BIT_DEPTH;
407  od->desc = SANE_DESC_BIT_DEPTH;
408  od->type = SANE_TYPE_INT;
409  od->unit = SANE_UNIT_NONE;
410  od->size = sizeof (SANE_Word);
411  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
412  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
413  od->constraint.word_list = depth_list;
414  test_device->val[opt_depth].w = init_depth;
415
416  /* opt_hand_scanner */
417  od = &test_device->opt[opt_hand_scanner];
418  od->name = "hand-scanner";
419  od->title = SANE_I18N ("Hand-scanner simulation");
420  od->desc = SANE_I18N ("Simulate a hand-scanner.  Hand-scanners do not "
421			"know the image height a priori.  Instead, they "
422			"return a height of -1.  Setting this option allows one "
423			"to test whether a frontend can handle this "
424			"correctly.  This option also enables a fixed width "
425			"of 11 cm.");
426  od->type = SANE_TYPE_BOOL;
427  od->unit = SANE_UNIT_NONE;
428  od->size = sizeof (SANE_Word);
429  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
430  od->constraint_type = SANE_CONSTRAINT_NONE;
431  od->constraint.range = 0;
432  test_device->val[opt_hand_scanner].w = init_hand_scanner;
433
434  /* opt_three_pass */
435  od = &test_device->opt[opt_three_pass];
436  od->name = "three-pass";
437  od->title = SANE_I18N ("Three-pass simulation");
438  od->desc = SANE_I18N ("Simulate a three-pass scanner. In color mode, three "
439			"frames are transmitted.");
440  od->type = SANE_TYPE_BOOL;
441  od->unit = SANE_UNIT_NONE;
442  od->size = sizeof (SANE_Word);
443  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
444  if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0)
445    od->cap |= SANE_CAP_INACTIVE;
446  od->constraint_type = SANE_CONSTRAINT_NONE;
447  od->constraint.range = 0;
448  test_device->val[opt_three_pass].w = init_three_pass;
449
450  /* opt_three_pass_order */
451  od = &test_device->opt[opt_three_pass_order];
452  od->name = "three-pass-order";
453  od->title = SANE_I18N ("Set the order of frames");
454  od->desc = SANE_I18N ("Set the order of frames in three-pass color mode.");
455  od->type = SANE_TYPE_STRING;
456  od->unit = SANE_UNIT_NONE;
457  od->size = (SANE_Int) max_string_size (order_list);
458  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
459  if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0)
460    od->cap |= SANE_CAP_INACTIVE;
461  if (!init_three_pass)
462    od->cap |= SANE_CAP_INACTIVE;
463  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
464  od->constraint.string_list = order_list;
465  test_device->val[opt_three_pass_order].s = malloc ((size_t) od->size);
466  if (!test_device->val[opt_three_pass_order].s)
467    goto fail;
468  strcpy (test_device->val[opt_three_pass_order].s, init_three_pass_order);
469
470  /* opt_resolution */
471  od = &test_device->opt[opt_resolution];
472  od->name = SANE_NAME_SCAN_RESOLUTION;
473  od->title = SANE_TITLE_SCAN_RESOLUTION;
474  od->desc = SANE_DESC_SCAN_RESOLUTION;
475  od->type = SANE_TYPE_FIXED;
476  od->unit = SANE_UNIT_DPI;
477  od->size = sizeof (SANE_Word);
478  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
479  od->constraint_type = SANE_CONSTRAINT_RANGE;
480  od->constraint.range = &resolution_range;
481  test_device->val[opt_resolution].w = init_resolution;
482
483  /* opt_scan_source */
484  od = &test_device->opt[opt_scan_source];
485  od->name = SANE_NAME_SCAN_SOURCE;
486  od->title = SANE_TITLE_SCAN_SOURCE;
487  od->desc = SANE_I18N("If Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.");
488  od->type = SANE_TYPE_STRING;
489  od->unit = SANE_UNIT_NONE;
490  od->size = (SANE_Int) max_string_size (source_list);
491  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
492  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
493  od->constraint.string_list = source_list;
494  test_device->val[opt_scan_source].s = malloc ((size_t) od->size);
495  if (!test_device->val[opt_scan_source].s)
496    goto fail;
497  strcpy (test_device->val[opt_scan_source].s, init_scan_source);
498
499  /* opt_special_group */
500  od = &test_device->opt[opt_special_group];
501  od->name = "";
502  od->title = SANE_I18N ("Special Options");
503  od->desc = "";
504  od->type = SANE_TYPE_GROUP;
505  od->unit = SANE_UNIT_NONE;
506  od->size = 0;
507  od->cap = 0;
508  od->constraint_type = SANE_CONSTRAINT_NONE;
509  od->constraint.range = 0;
510  test_device->val[opt_special_group].w = 0;
511
512  /* opt_test_picture */
513  od = &test_device->opt[opt_test_picture];
514  od->name = "test-picture";
515  od->title = SANE_I18N ("Select the test picture");
516  od->desc =
517    SANE_I18N ("Select the kind of test picture. Available options:\n"
518	       "Solid black: fills the whole scan with black.\n"
519	       "Solid white: fills the whole scan with white.\n"
520	       "Color pattern: draws various color test patterns "
521	       "depending on the mode.\n"
522	       "Grid: draws a black/white grid with a width and "
523	       "height of 10 mm per square.");
524  od->type = SANE_TYPE_STRING;
525  od->unit = SANE_UNIT_NONE;
526  od->size = (SANE_Int) max_string_size (test_picture_list);
527  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
528  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
529  od->constraint.string_list = test_picture_list;
530  test_device->val[opt_test_picture].s = malloc ((size_t) od->size);
531  if (!test_device->val[opt_test_picture].s)
532    goto fail;
533  strcpy (test_device->val[opt_test_picture].s, init_test_picture);
534
535  /* opt_invert_endianness */
536  od = &test_device->opt[opt_invert_endianess];
537  od->name = "invert-endianess";
538  od->title = SANE_I18N ("Invert endianness");
539  od->desc = SANE_I18N ("Exchange upper and lower byte of image data in 16 "
540			"bit modes. This option can be used to test the 16 "
541			"bit modes of frontends, e.g. if the frontend uses "
542			"the correct endianness.");
543  od->type = SANE_TYPE_BOOL;
544  od->unit = SANE_UNIT_NONE;
545  od->size = sizeof (SANE_Word);
546  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
547  od->cap |= SANE_CAP_INACTIVE;
548  od->constraint_type = SANE_CONSTRAINT_NONE;
549  od->constraint.range = 0;
550  test_device->val[opt_invert_endianess].w = init_invert_endianess;
551
552  /* opt_read_limit */
553  od = &test_device->opt[opt_read_limit];
554  od->name = "read-limit";
555  od->title = SANE_I18N ("Read limit");
556  od->desc = SANE_I18N ("Limit the amount of data transferred with each "
557			"call to sane_read().");
558  od->type = SANE_TYPE_BOOL;
559  od->unit = SANE_UNIT_NONE;
560  od->size = sizeof (SANE_Word);
561  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
562  od->constraint_type = SANE_CONSTRAINT_NONE;
563  od->constraint.range = 0;
564  test_device->val[opt_read_limit].w = init_read_limit;
565
566  /* opt_read_limit_size */
567  od = &test_device->opt[opt_read_limit_size];
568  od->name = "read-limit-size";
569  od->title = SANE_I18N ("Size of read-limit");
570  od->desc = SANE_I18N ("The (maximum) amount of data transferred with each "
571			"call to sane_read().");
572  od->type = SANE_TYPE_INT;
573  od->unit = SANE_UNIT_NONE;
574  od->size = sizeof (SANE_Word);
575  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
576  if (!init_read_limit)
577    od->cap |= SANE_CAP_INACTIVE;
578  od->constraint_type = SANE_CONSTRAINT_RANGE;
579  od->constraint.range = &read_limit_size_range;
580  test_device->val[opt_read_limit_size].w = init_read_limit_size;
581
582  /* opt_read_delay */
583  od = &test_device->opt[opt_read_delay];
584  od->name = "read-delay";
585  od->title = SANE_I18N ("Read delay");
586  od->desc = SANE_I18N ("Delay the transfer of data to the pipe.");
587  od->type = SANE_TYPE_BOOL;
588  od->unit = SANE_UNIT_NONE;
589  od->size = sizeof (SANE_Word);
590  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
591  od->constraint_type = SANE_CONSTRAINT_NONE;
592  od->constraint.range = 0;
593  test_device->val[opt_read_delay].w = init_read_delay;
594
595  /* opt_read_delay_duration */
596  od = &test_device->opt[opt_read_delay_duration];
597  od->name = "read-delay-duration";
598  od->title = SANE_I18N ("Duration of read-delay");
599  od->desc = SANE_I18N ("How long to wait after transferring each buffer of "
600			"data through the pipe.");
601  od->type = SANE_TYPE_INT;
602  od->unit = SANE_UNIT_MICROSECOND;
603  od->size = sizeof (SANE_Word);
604  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
605  if (!init_read_delay)
606    od->cap |= SANE_CAP_INACTIVE;
607  od->constraint_type = SANE_CONSTRAINT_RANGE;
608  od->constraint.range = &read_delay_duration_range;
609  test_device->val[opt_read_delay_duration].w = init_read_delay_duration;
610
611  /* opt_read_status_code */
612  od = &test_device->opt[opt_read_status_code];
613  od->name = "read-return-value";
614  od->title = SANE_I18N ("Return-value of sane_read");
615  od->desc =
616    SANE_I18N ("Select the return-value of sane_read(). \"Default\" "
617	       "is the normal handling for scanning. All other status "
618	       "codes are for testing how the frontend handles them.");
619  od->type = SANE_TYPE_STRING;
620  od->unit = SANE_UNIT_NONE;
621  od->size = (SANE_Int) max_string_size (read_status_code_list);
622  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
623  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
624  od->constraint.string_list = read_status_code_list;
625  test_device->val[opt_read_status_code].s = malloc ((size_t) od->size);
626  if (!test_device->val[opt_read_status_code].s)
627    goto fail;
628  strcpy (test_device->val[opt_read_status_code].s, init_read_status_code);
629
630  /* opt_ppl_loss */
631  od = &test_device->opt[opt_ppl_loss];
632  od->name = "ppl-loss";
633  od->title = SANE_I18N ("Loss of pixels per line");
634  od->desc =
635    SANE_I18N ("The number of pixels that are wasted at the end of each "
636	       "line.");
637  od->type = SANE_TYPE_INT;
638  od->unit = SANE_UNIT_PIXEL;
639  od->size = sizeof (SANE_Word);
640  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
641  od->constraint_type = SANE_CONSTRAINT_RANGE;
642  od->constraint.range = &ppl_loss_range;
643  test_device->val[opt_ppl_loss].w = init_ppl_loss;
644
645  /* opt_fuzzy_parameters */
646  od = &test_device->opt[opt_fuzzy_parameters];
647  od->name = "fuzzy-parameters";
648  od->title = SANE_I18N ("Fuzzy parameters");
649  od->desc = SANE_I18N ("Return fuzzy lines and bytes per line when "
650			"sane_parameters() is called before sane_start().");
651  od->type = SANE_TYPE_BOOL;
652  od->unit = SANE_UNIT_NONE;
653  od->size = sizeof (SANE_Word);
654  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
655  od->constraint_type = SANE_CONSTRAINT_NONE;
656  od->constraint.range = 0;
657  test_device->val[opt_fuzzy_parameters].w = init_fuzzy_parameters;
658
659  /* opt_non_blocking */
660  od = &test_device->opt[opt_non_blocking];
661  od->name = "non-blocking";
662  od->title = SANE_I18N ("Use non-blocking IO");
663  od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported "
664			"by the frontend.");
665  od->type = SANE_TYPE_BOOL;
666  od->unit = SANE_UNIT_NONE;
667  od->size = sizeof (SANE_Word);
668  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
669  od->constraint_type = SANE_CONSTRAINT_NONE;
670  od->constraint.range = 0;
671  test_device->val[opt_non_blocking].w = init_non_blocking;
672
673  /* opt_select_fd */
674  od = &test_device->opt[opt_select_fd];
675  od->name = "select-fd";
676  od->title = SANE_I18N ("Offer select file descriptor");
677  od->desc = SANE_I18N ("Offer a select filedescriptor for detecting if "
678			"sane_read() will return data.");
679  od->type = SANE_TYPE_BOOL;
680  od->unit = SANE_UNIT_NONE;
681  od->size = sizeof (SANE_Word);
682  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
683  od->constraint_type = SANE_CONSTRAINT_NONE;
684  od->constraint.range = 0;
685  test_device->val[opt_select_fd].w = init_select_fd;
686
687  /* opt_enable_test_options */
688  od = &test_device->opt[opt_enable_test_options];
689  od->name = "enable-test-options";
690  od->title = SANE_I18N ("Enable test options");
691  od->desc = SANE_I18N ("Enable various test options. This is for testing "
692			"the ability of frontends to view and modify all the "
693			"different SANE option types.");
694  od->type = SANE_TYPE_BOOL;
695  od->unit = SANE_UNIT_NONE;
696  od->size = sizeof (SANE_Word);
697  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
698  od->constraint_type = SANE_CONSTRAINT_NONE;
699  od->constraint.range = 0;
700  test_device->val[opt_enable_test_options].w = init_enable_test_options;
701
702  /* opt_print_options */
703  od = &test_device->opt[opt_print_options];
704  od->name = "print-options";
705  od->title = SANE_I18N ("Print options");
706  od->desc = SANE_I18N ("Print a list of all options.");
707  od->type = SANE_TYPE_BUTTON;
708  od->unit = SANE_UNIT_NONE;
709  od->size = 0;
710  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
711  od->constraint_type = SANE_CONSTRAINT_NONE;
712  od->constraint.string_list = 0;
713  test_device->val[opt_print_options].w = 0;
714
715  /* opt_geometry_group */
716  od = &test_device->opt[opt_geometry_group];
717  od->name = "";
718  od->title = SANE_I18N ("Geometry");
719  od->desc = "";
720  od->type = SANE_TYPE_GROUP;
721  od->unit = SANE_UNIT_NONE;
722  od->size = 0;
723  od->cap = 0;
724  od->constraint_type = SANE_CONSTRAINT_NONE;
725  od->constraint.range = 0;
726  test_device->val[opt_geometry_group].w = 0;
727
728  /* opt_tl_x */
729  od = &test_device->opt[opt_tl_x];
730  od->name = SANE_NAME_SCAN_TL_X;
731  od->title = SANE_TITLE_SCAN_TL_X;
732  od->desc = SANE_DESC_SCAN_TL_X;
733  od->type = SANE_TYPE_FIXED;
734  od->unit = SANE_UNIT_MM;
735  od->size = sizeof (SANE_Word);
736  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
737  od->constraint_type = SANE_CONSTRAINT_RANGE;
738  od->constraint.range = &geometry_range;
739  test_device->val[opt_tl_x].w = init_tl_x;
740
741  /* opt_tl_y */
742  od = &test_device->opt[opt_tl_y];
743  od->name = SANE_NAME_SCAN_TL_Y;
744  od->title = SANE_TITLE_SCAN_TL_Y;
745  od->desc = SANE_DESC_SCAN_TL_Y;
746  od->type = SANE_TYPE_FIXED;
747  od->unit = SANE_UNIT_MM;
748  od->size = sizeof (SANE_Word);
749  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
750  od->constraint_type = SANE_CONSTRAINT_RANGE;
751  od->constraint.range = &geometry_range;
752  test_device->val[opt_tl_y].w = init_tl_y;
753
754  /* opt_br_x */
755  od = &test_device->opt[opt_br_x];
756  od->name = SANE_NAME_SCAN_BR_X;
757  od->title = SANE_TITLE_SCAN_BR_X;
758  od->desc = SANE_DESC_SCAN_BR_X;
759  od->type = SANE_TYPE_FIXED;
760  od->unit = SANE_UNIT_MM;
761  od->size = sizeof (SANE_Word);
762  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
763  od->constraint_type = SANE_CONSTRAINT_RANGE;
764  od->constraint.range = &geometry_range;
765  test_device->val[opt_br_x].w = init_br_x;
766
767  /* opt_br_y */
768  od = &test_device->opt[opt_br_y];
769  od->name = SANE_NAME_SCAN_BR_Y;
770  od->title = SANE_TITLE_SCAN_BR_Y;
771  od->desc = SANE_DESC_SCAN_BR_Y;
772  od->type = SANE_TYPE_FIXED;
773  od->unit = SANE_UNIT_MM;
774  od->size = sizeof (SANE_Word);
775  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
776  od->constraint_type = SANE_CONSTRAINT_RANGE;
777  od->constraint.range = &geometry_range;
778  test_device->val[opt_br_y].w = init_br_y;
779
780  /* opt_bool_group */
781  od = &test_device->opt[opt_bool_group];
782  od->name = "";
783  od->title = SANE_I18N ("Bool test options");
784  od->desc = "";
785  od->type = SANE_TYPE_GROUP;
786  od->unit = SANE_UNIT_NONE;
787  od->size = 0;
788  od->cap = SANE_CAP_ADVANCED;
789  od->constraint_type = SANE_CONSTRAINT_NONE;
790  od->constraint.range = 0;
791  test_device->val[opt_bool_group].w = 0;
792
793  /* opt_bool_soft_select_soft_detect */
794  od = &test_device->opt[opt_bool_soft_select_soft_detect];
795  od->name = "bool-soft-select-soft-detect";
796  od->title = SANE_I18N ("(1/6) Bool soft select soft detect");
797  od->desc =
798    SANE_I18N ("(1/6) Bool test option that has soft select and soft "
799	       "detect (and advanced) capabilities. That's just a "
800	       "normal bool option.");
801  od->type = SANE_TYPE_BOOL;
802  od->unit = SANE_UNIT_NONE;
803  od->size = sizeof (SANE_Word);
804  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
805  if (init_enable_test_options == SANE_FALSE)
806    od->cap |= SANE_CAP_INACTIVE;
807  od->constraint_type = SANE_CONSTRAINT_NONE;
808  od->constraint.range = 0;
809  test_device->val[opt_bool_soft_select_soft_detect].w = SANE_FALSE;
810
811  /* opt_bool_hard_select_soft_detect */
812  od = &test_device->opt[opt_bool_hard_select_soft_detect];
813  od->name = "bool-hard-select-soft-detect";
814  od->title = SANE_I18N ("(2/6) Bool hard select soft detect");
815  od->desc =
816    SANE_I18N ("(2/6) Bool test option that has hard select and soft "
817	       "detect (and advanced) capabilities. That means the "
818	       "option can't be set by the frontend but by the user "
819	       "(e.g. by pressing a button at the device).");
820  od->type = SANE_TYPE_BOOL;
821  od->unit = SANE_UNIT_NONE;
822  od->size = sizeof (SANE_Word);
823  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
824  if (init_enable_test_options == SANE_FALSE)
825    od->cap |= SANE_CAP_INACTIVE;
826  od->constraint_type = SANE_CONSTRAINT_NONE;
827  od->constraint.range = 0;
828  test_device->val[opt_bool_hard_select_soft_detect].w = SANE_FALSE;
829
830  /* opt_bool_hard_select */
831  od = &test_device->opt[opt_bool_hard_select];
832  od->name = "bool-hard-select";
833  od->title = SANE_I18N ("(3/6) Bool hard select");
834  od->desc = SANE_I18N ("(3/6) Bool test option that has hard select "
835			"(and advanced) capabilities. That means the option "
836			"can't be set by the frontend but by the user "
837			"(e.g. by pressing a button at the device) and can't "
838			"be read by the frontend.");
839  od->type = SANE_TYPE_BOOL;
840  od->unit = SANE_UNIT_NONE;
841  od->size = sizeof (SANE_Word);
842  od->cap = SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
843  if (init_enable_test_options == SANE_FALSE)
844    od->cap |= SANE_CAP_INACTIVE;
845  od->constraint_type = SANE_CONSTRAINT_NONE;
846  od->constraint.range = 0;
847  test_device->val[opt_bool_hard_select].w = SANE_FALSE;
848
849  /* opt_bool_soft_detect */
850  od = &test_device->opt[opt_bool_soft_detect];
851  od->name = "bool-soft-detect";
852  od->title = SANE_I18N ("(4/6) Bool soft detect");
853  od->desc = SANE_I18N ("(4/6) Bool test option that has soft detect "
854			"(and advanced) capabilities. That means the option "
855			"is read-only.");
856  od->type = SANE_TYPE_BOOL;
857  od->unit = SANE_UNIT_NONE;
858  od->size = sizeof (SANE_Word);
859  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
860  if (init_enable_test_options == SANE_FALSE)
861    od->cap |= SANE_CAP_INACTIVE;
862  od->constraint_type = SANE_CONSTRAINT_NONE;
863  od->constraint.range = 0;
864  test_device->val[opt_bool_soft_detect].w = SANE_FALSE;
865
866  /* opt_bool_soft_select_soft_detect_emulated */
867  od = &test_device->opt[opt_bool_soft_select_soft_detect_emulated];
868  od->name = "bool-soft-select-soft-detect-emulated";
869  od->title = SANE_I18N ("(5/6) Bool soft select soft detect emulated");
870  od->desc = SANE_I18N ("(5/6) Bool test option that has soft select, soft "
871			"detect, and emulated (and advanced) capabilities.");
872  od->type = SANE_TYPE_BOOL;
873  od->unit = SANE_UNIT_NONE;
874  od->size = sizeof (SANE_Word);
875  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED
876    | SANE_CAP_EMULATED;
877  if (init_enable_test_options == SANE_FALSE)
878    od->cap |= SANE_CAP_INACTIVE;
879  od->constraint_type = SANE_CONSTRAINT_NONE;
880  od->constraint.range = 0;
881  test_device->val[opt_bool_soft_select_soft_detect_emulated].w = SANE_FALSE;
882
883  /* opt_bool_soft_select_soft_detect_auto */
884  od = &test_device->opt[opt_bool_soft_select_soft_detect_auto];
885  od->name = "bool-soft-select-soft-detect-auto";
886  od->title = SANE_I18N ("(6/6) Bool soft select soft detect auto");
887  od->desc = SANE_I18N ("(6/6) Bool test option that has soft select, soft "
888			"detect, and automatic (and advanced) capabilities. "
889			"This option can be automatically set by the backend.");
890  od->type = SANE_TYPE_BOOL;
891  od->unit = SANE_UNIT_NONE;
892  od->size = sizeof (SANE_Word);
893  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED
894    | SANE_CAP_AUTOMATIC;
895  if (init_enable_test_options == SANE_FALSE)
896    od->cap |= SANE_CAP_INACTIVE;
897  od->constraint_type = SANE_CONSTRAINT_NONE;
898  od->constraint.range = 0;
899  test_device->val[opt_bool_soft_select_soft_detect_auto].w = SANE_FALSE;
900
901  /* opt_int_group */
902  od = &test_device->opt[opt_int_group];
903  od->name = "";
904  od->title = SANE_I18N ("Int test options");
905  od->desc = "";
906  od->type = SANE_TYPE_GROUP;
907  od->unit = SANE_UNIT_NONE;
908  od->size = 0;
909  od->cap = SANE_CAP_ADVANCED;
910  od->constraint_type = SANE_CONSTRAINT_NONE;
911  od->constraint.range = 0;
912  test_device->val[opt_int_group].w = 0;
913
914  /* opt_int */
915  od = &test_device->opt[opt_int];
916  od->name = "int";
917  od->title = SANE_I18N ("(1/7) Int");
918  od->desc = SANE_I18N ("(1/7) Int test option with no unit and no "
919			"constraint set.");
920  od->type = SANE_TYPE_INT;
921  od->unit = SANE_UNIT_NONE;
922  od->size = sizeof (SANE_Word);
923  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
924  if (init_enable_test_options == SANE_FALSE)
925    od->cap |= SANE_CAP_INACTIVE;
926  od->constraint_type = SANE_CONSTRAINT_NONE;
927  od->constraint.range = 0;
928  test_device->val[opt_int].w = 42;
929
930  /* opt_int_constraint_range */
931  od = &test_device->opt[opt_int_constraint_range];
932  od->name = "int-constraint-range";
933  od->title = SANE_I18N ("(2/7) Int constraint range");
934  od->desc = SANE_I18N ("(2/7) Int test option with unit pixel and "
935			"constraint range set. Minimum is 4, maximum 192, and "
936			"quant is 2.");
937  od->type = SANE_TYPE_INT;
938  od->unit = SANE_UNIT_PIXEL;
939  od->size = sizeof (SANE_Word);
940  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
941  if (init_enable_test_options == SANE_FALSE)
942    od->cap |= SANE_CAP_INACTIVE;
943  od->constraint_type = SANE_CONSTRAINT_RANGE;
944  od->constraint.range = &int_constraint_range;
945  test_device->val[opt_int_constraint_range].w = 26;
946
947  /* opt_int_constraint_word_list */
948  od = &test_device->opt[opt_int_constraint_word_list];
949  od->name = "int-constraint-word-list";
950  od->title = SANE_I18N ("(3/7) Int constraint word list");
951  od->desc = SANE_I18N ("(3/7) Int test option with unit bits and "
952			"constraint word list set.");
953  od->type = SANE_TYPE_INT;
954  od->unit = SANE_UNIT_BIT;
955  od->size = sizeof (SANE_Word);
956  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
957  if (init_enable_test_options == SANE_FALSE)
958    od->cap |= SANE_CAP_INACTIVE;
959  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
960  od->constraint.word_list = int_constraint_word_list;
961  test_device->val[opt_int_constraint_word_list].w = 42;
962
963  /* opt_int_array */
964  od = &test_device->opt[opt_int_array];
965  od->name = "int-constraint-array";
966  od->title = SANE_I18N ("(4/7) Int array");
967  od->desc = SANE_I18N ("(4/7) Int test option with unit mm and using "
968			"an array without constraints.");
969  od->type = SANE_TYPE_INT;
970  od->unit = SANE_UNIT_MM;
971  od->size = 6 * sizeof (SANE_Word);
972  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
973  if (init_enable_test_options == SANE_FALSE)
974    od->cap |= SANE_CAP_INACTIVE;
975  od->constraint_type = SANE_CONSTRAINT_NONE;
976  od->constraint.range = 0;
977  test_device->val[opt_int_array].wa = &int_array[0];
978
979  /* opt_int_array_constraint_range */
980  od = &test_device->opt[opt_int_array_constraint_range];
981  od->name = "int-constraint-array-constraint-range";
982  od->title = SANE_I18N ("(5/7) Int array constraint range");
983  od->desc = SANE_I18N ("(5/7) Int test option with unit dpi and using "
984			"an array with a range constraint. Minimum is 4, "
985			"maximum 192, and quant is 2.");
986  od->type = SANE_TYPE_INT;
987  od->unit = SANE_UNIT_DPI;
988  od->size = 6 * sizeof (SANE_Word);
989  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
990  if (init_enable_test_options == SANE_FALSE)
991    od->cap |= SANE_CAP_INACTIVE;
992  od->constraint_type = SANE_CONSTRAINT_RANGE;
993  od->constraint.range = &int_constraint_range;
994  test_device->val[opt_int_array_constraint_range].wa =
995    &int_array_constraint_range[0];
996
997 /* opt_int_array_constraint_word_list */
998  od = &test_device->opt[opt_int_array_constraint_word_list];
999  od->name = "int-constraint-array-constraint-word-list";
1000  od->title = SANE_I18N ("(6/7) Int array constraint word list");
1001  od->desc = SANE_I18N ("(6/7) Int test option with unit percent and using "
1002			"an array with a word list constraint.");
1003  od->type = SANE_TYPE_INT;
1004  od->unit = SANE_UNIT_PERCENT;
1005  od->size = 6 * sizeof (SANE_Word);
1006  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1007  if (init_enable_test_options == SANE_FALSE)
1008    od->cap |= SANE_CAP_INACTIVE;
1009  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1010  od->constraint.word_list = int_constraint_word_list;
1011  test_device->val[opt_int_array_constraint_word_list].wa =
1012    &int_array_constraint_word_list[0];
1013
1014  /* opt_int_inexact */
1015  od = &test_device->opt[opt_int_inexact];
1016  od->name = "int-inexact";
1017  od->title = SANE_I18N ("(7/7) Int inexact");
1018  od->desc = SANE_I18N ("(7/7) Int test option that modifies the value "
1019			"and returns SANE_INFO_INEXACT.");
1020  od->type = SANE_TYPE_INT;
1021  od->unit = SANE_UNIT_NONE;
1022  od->size = sizeof (SANE_Word);
1023  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1024  if (init_enable_test_options == SANE_FALSE)
1025    od->cap |= SANE_CAP_INACTIVE;
1026  od->constraint_type = SANE_CONSTRAINT_NONE;
1027  od->constraint.range = 0;
1028  test_device->val[opt_int_inexact].w = 67;
1029
1030
1031  /* opt_gamma_red */
1032  init_gamma_table(gamma_red, GAMMA_RED_SIZE, gamma_range.max);
1033  od = &test_device->opt[opt_gamma_red];
1034  od->name = SANE_NAME_GAMMA_VECTOR_R;
1035  od->title = SANE_TITLE_GAMMA_VECTOR_R;
1036  od->desc = SANE_DESC_GAMMA_VECTOR_R;
1037  od->type = SANE_TYPE_INT;
1038  od->unit = SANE_UNIT_NONE;
1039  od->size = 256 * sizeof (SANE_Word);
1040  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1041  od->constraint_type = SANE_CONSTRAINT_RANGE;
1042  od->constraint.range = &gamma_range;
1043  test_device->val[opt_gamma_red].wa = &gamma_red[0];
1044
1045  /* opt_gamma_green */
1046  init_gamma_table(gamma_green, GAMMA_GREEN_SIZE, gamma_range.max);
1047  od = &test_device->opt[opt_gamma_green];
1048  od->name = SANE_NAME_GAMMA_VECTOR_G;
1049  od->title = SANE_TITLE_GAMMA_VECTOR_G;
1050  od->desc = SANE_DESC_GAMMA_VECTOR_G;
1051  od->type = SANE_TYPE_INT;
1052  od->unit = SANE_UNIT_NONE;
1053  od->size = 256 * sizeof (SANE_Word);
1054  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1055  od->constraint_type = SANE_CONSTRAINT_RANGE;
1056  od->constraint.range = &gamma_range;
1057  test_device->val[opt_gamma_green].wa = &gamma_green[0];
1058
1059  /* opt_gamma_blue */
1060  init_gamma_table(gamma_blue, GAMMA_BLUE_SIZE, gamma_range.max);
1061  od = &test_device->opt[opt_gamma_blue];
1062  od->name = SANE_NAME_GAMMA_VECTOR_B;
1063  od->title = SANE_TITLE_GAMMA_VECTOR_B;
1064  od->desc = SANE_DESC_GAMMA_VECTOR_B;
1065  od->type = SANE_TYPE_INT;
1066  od->unit = SANE_UNIT_NONE;
1067  od->size = 256 * sizeof (SANE_Word);
1068  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1069  od->constraint_type = SANE_CONSTRAINT_RANGE;
1070  od->constraint.range = &gamma_range;
1071  test_device->val[opt_gamma_blue].wa = &gamma_blue[0];
1072
1073  /* opt_gamma_all */
1074  init_gamma_table(gamma_all, GAMMA_ALL_SIZE, gamma_range.max);
1075  print_gamma_table(gamma_all, GAMMA_ALL_SIZE);
1076  od = &test_device->opt[opt_gamma_all];
1077  od->name = SANE_NAME_GAMMA_VECTOR;
1078  od->title = SANE_TITLE_GAMMA_VECTOR;
1079  od->desc = SANE_DESC_GAMMA_VECTOR;
1080  od->type = SANE_TYPE_INT;
1081  od->unit = SANE_UNIT_NONE;
1082  od->size = GAMMA_ALL_SIZE * sizeof (SANE_Word);
1083  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1084  od->constraint_type = SANE_CONSTRAINT_RANGE;
1085  od->constraint.range = &gamma_range;
1086  test_device->val[opt_gamma_all].wa = &gamma_all[0];
1087
1088  /* opt_fixed_group */
1089  od = &test_device->opt[opt_fixed_group];
1090  od->name = "";
1091  od->title = SANE_I18N ("Fixed test options");
1092  od->desc = "";
1093  od->type = SANE_TYPE_GROUP;
1094  od->unit = SANE_UNIT_NONE;
1095  od->size = 0;
1096  od->cap = SANE_CAP_ADVANCED;
1097  od->constraint_type = SANE_CONSTRAINT_NONE;
1098  od->constraint.range = 0;
1099  test_device->val[opt_fixed_group].w = 0;
1100
1101  /* opt_fixed */
1102  od = &test_device->opt[opt_fixed];
1103  od->name = "fixed";
1104  od->title = SANE_I18N ("(1/3) Fixed");
1105  od->desc = SANE_I18N ("(1/3) Fixed test option with no unit and no "
1106			"constraint set.");
1107  od->type = SANE_TYPE_FIXED;
1108  od->unit = SANE_UNIT_NONE;
1109  od->size = sizeof (SANE_Word);
1110  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1111  if (init_enable_test_options == SANE_FALSE)
1112    od->cap |= SANE_CAP_INACTIVE;
1113  od->constraint_type = SANE_CONSTRAINT_NONE;
1114  od->constraint.range = 0;
1115  test_device->val[opt_fixed].w = SANE_FIX (42.0);
1116
1117  /* opt_fixed_constraint_range */
1118  od = &test_device->opt[opt_fixed_constraint_range];
1119  od->name = "fixed-constraint-range";
1120  od->title = SANE_I18N ("(2/3) Fixed constraint range");
1121  od->desc = SANE_I18N ("(2/3) Fixed test option with unit microsecond and "
1122			"constraint range set. Minimum is -42.17, maximum "
1123			"32767.9999, and quant is 2.0.");
1124  od->type = SANE_TYPE_FIXED;
1125  od->unit = SANE_UNIT_MICROSECOND;
1126  od->size = sizeof (SANE_Word);
1127  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1128  if (init_enable_test_options == SANE_FALSE)
1129    od->cap |= SANE_CAP_INACTIVE;
1130  od->constraint_type = SANE_CONSTRAINT_RANGE;
1131  od->constraint.range = &fixed_constraint_range;
1132  test_device->val[opt_fixed_constraint_range].w = SANE_FIX (41.83);
1133
1134  /* opt_fixed_constraint_word_list */
1135  od = &test_device->opt[opt_fixed_constraint_word_list];
1136  od->name = "fixed-constraint-word-list";
1137  od->title = SANE_I18N ("(3/3) Fixed constraint word list");
1138  od->desc = SANE_I18N ("(3/3) Fixed test option with no unit and "
1139			"constraint word list set.");
1140  od->type = SANE_TYPE_FIXED;
1141  od->unit = SANE_UNIT_NONE;
1142  od->size = sizeof (SANE_Word);
1143  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1144  if (init_enable_test_options == SANE_FALSE)
1145    od->cap |= SANE_CAP_INACTIVE;
1146  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1147  od->constraint.word_list = fixed_constraint_word_list;
1148  test_device->val[opt_fixed_constraint_word_list].w = SANE_FIX (42.0);
1149
1150  /* opt_string_group */
1151  od = &test_device->opt[opt_string_group];
1152  od->name = "";
1153  od->title = SANE_I18N ("String test options");
1154  od->desc = "";
1155  od->type = SANE_TYPE_GROUP;
1156  od->unit = SANE_UNIT_NONE;
1157  od->size = 0;
1158  od->cap = 0;
1159  od->constraint_type = SANE_CONSTRAINT_NONE;
1160  od->constraint.range = 0;
1161  test_device->val[opt_string_group].w = 0;
1162
1163  /* opt_string */
1164  od = &test_device->opt[opt_string];
1165  od->name = "string";
1166  od->title = SANE_I18N ("(1/3) String");
1167  od->desc = SANE_I18N ("(1/3) String test option without constraint.");
1168  od->type = SANE_TYPE_STRING;
1169  od->unit = SANE_UNIT_NONE;
1170  od->size = (SANE_Int) strlen (init_string) + 1;
1171  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1172  if (init_enable_test_options == SANE_FALSE)
1173    od->cap |= SANE_CAP_INACTIVE;
1174  od->constraint_type = SANE_CONSTRAINT_NONE;
1175  od->constraint.string_list = 0;
1176  test_device->val[opt_string].s = malloc ((size_t) od->size);
1177  if (!test_device->val[opt_string].s)
1178    goto fail;
1179  strcpy (test_device->val[opt_string].s, init_string);
1180
1181  /* opt_string_constraint_string_list */
1182  od = &test_device->opt[opt_string_constraint_string_list];
1183  od->name = "string-constraint-string-list";
1184  od->title = SANE_I18N ("(2/3) String constraint string list");
1185  od->desc = SANE_I18N ("(2/3) String test option with string list "
1186			"constraint.");
1187  od->type = SANE_TYPE_STRING;
1188  od->unit = SANE_UNIT_NONE;
1189  od->size = (SANE_Int) max_string_size (string_constraint_string_list);
1190  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1191  if (init_enable_test_options == SANE_FALSE)
1192    od->cap |= SANE_CAP_INACTIVE;
1193  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1194  od->constraint.string_list = string_constraint_string_list;
1195  test_device->val[opt_string_constraint_string_list].s = malloc ((size_t) od->size);
1196  if (!test_device->val[opt_string_constraint_string_list].s)
1197    goto fail;
1198  strcpy (test_device->val[opt_string_constraint_string_list].s,
1199	  init_string_constraint_string_list);
1200
1201  /* opt_string_constraint_long_string_list */
1202  od = &test_device->opt[opt_string_constraint_long_string_list];
1203  od->name = "string-constraint-long-string-list";
1204  od->title = SANE_I18N ("(3/3) String constraint long string list");
1205  od->desc = SANE_I18N ("(3/3) String test option with string list "
1206			"constraint. Contains some more entries...");
1207  od->type = SANE_TYPE_STRING;
1208  od->unit = SANE_UNIT_NONE;
1209  od->size = (SANE_Int) max_string_size (string_constraint_long_string_list);
1210  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1211  if (init_enable_test_options == SANE_FALSE)
1212    od->cap |= SANE_CAP_INACTIVE;
1213  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1214  od->constraint.string_list = string_constraint_long_string_list;
1215  test_device->val[opt_string_constraint_long_string_list].s =
1216    malloc ((size_t) od->size);
1217  if (!test_device->val[opt_string_constraint_long_string_list].s)
1218    goto fail;
1219  strcpy (test_device->val[opt_string_constraint_long_string_list].s,
1220	  init_string_constraint_long_string_list);
1221
1222  /* opt_button_group */
1223  od = &test_device->opt[opt_button_group];
1224  od->name = "";
1225  od->title = SANE_I18N ("Button test options");
1226  od->desc = "";
1227  od->type = SANE_TYPE_GROUP;
1228  od->unit = SANE_UNIT_NONE;
1229  od->size = 0;
1230  od->cap = 0;
1231  od->constraint_type = SANE_CONSTRAINT_NONE;
1232  od->constraint.range = 0;
1233  test_device->val[opt_button_group].w = 0;
1234
1235  /* opt_button */
1236  od = &test_device->opt[opt_button];
1237  od->name = "button";
1238  od->title = SANE_I18N ("(1/1) Button");
1239  od->desc = SANE_I18N ("(1/1) Button test option. Prints some text...");
1240  od->type = SANE_TYPE_BUTTON;
1241  od->unit = SANE_UNIT_NONE;
1242  od->size = 0;
1243  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1244  if (init_enable_test_options == SANE_FALSE)
1245    od->cap |= SANE_CAP_INACTIVE;
1246  od->constraint_type = SANE_CONSTRAINT_NONE;
1247  od->constraint.string_list = 0;
1248  test_device->val[opt_button].w = 0;
1249
1250  return SANE_STATUS_GOOD;
1251
1252fail:
1253  cleanup_options (test_device);
1254  return SANE_STATUS_NO_MEM;
1255}
1256
1257static void
1258cleanup_initial_string_values ()
1259{
1260  // Cleanup backing memory for initial values of string options.
1261  free (init_mode);
1262  init_mode = NULL;
1263  free (init_three_pass_order);
1264  init_three_pass_order = NULL;
1265  free (init_scan_source);
1266  init_scan_source = NULL;
1267  free (init_test_picture);
1268  init_test_picture = NULL;
1269  free (init_read_status_code);
1270  init_read_status_code = NULL;
1271  free (init_string);
1272  init_string = NULL;
1273  free (init_string_constraint_string_list);
1274  init_string_constraint_string_list = NULL;
1275  free (init_string_constraint_long_string_list);
1276  init_string_constraint_long_string_list = NULL;
1277}
1278
1279static void
1280cleanup_test_device (Test_Device * test_device)
1281{
1282  DBG (2, "cleanup_test_device: test_device=%p\n", (void *) test_device);
1283  if (test_device->options_initialized)
1284    cleanup_options (test_device);
1285  if (test_device->name)
1286    free (test_device->name);
1287  free (test_device);
1288}
1289
1290static SANE_Status
1291read_option (SANE_String line, SANE_String option_string,
1292	     parameter_type p_type, void *value)
1293{
1294  SANE_String_Const cp;
1295  SANE_Char *word, *end;
1296
1297  word = 0;
1298
1299  cp = sanei_config_get_string (line, &word);
1300
1301  if (!word)
1302    return SANE_STATUS_INVAL;
1303
1304  if (strcmp (word, option_string) != 0)
1305    {
1306      free(word);
1307      return SANE_STATUS_INVAL;
1308    }
1309
1310  free (word);
1311  word = 0;
1312
1313  switch (p_type)
1314    {
1315    case param_none:
1316      return SANE_STATUS_GOOD;
1317    case param_bool:
1318      {
1319	cp = sanei_config_get_string (cp, &word);
1320	if (!word)
1321	  return SANE_STATUS_INVAL;
1322	if (strlen (word) == 0)
1323	  {
1324	    DBG (3, "read_option: option `%s' requires parameter\n",
1325		 option_string);
1326	    return SANE_STATUS_INVAL;
1327	  }
1328	if (strcmp (word, "true") != 0 && strcmp (word, "false") != 0)
1329	  {
1330	    DBG (3, "read_option: option `%s' requires parameter "
1331		 "`true' or `false'\n", option_string);
1332	    return SANE_STATUS_INVAL;
1333	  }
1334	else if (strcmp (word, "true") == 0)
1335	  *(SANE_Bool *) value = SANE_TRUE;
1336	else
1337	  *(SANE_Bool *) value = SANE_FALSE;
1338	DBG (3, "read_option: set option `%s' to %s\n", option_string,
1339	     *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
1340	break;
1341      }
1342    case param_int:
1343      {
1344	SANE_Int int_value;
1345
1346	cp = sanei_config_get_string (cp, &word);
1347	if (!word)
1348	  return SANE_STATUS_INVAL;
1349	errno = 0;
1350	int_value = (SANE_Int) strtol (word, &end, 0);
1351	if (end == word)
1352	  {
1353	    DBG (3, "read_option: option `%s' requires parameter\n",
1354		 option_string);
1355	    return SANE_STATUS_INVAL;
1356	  }
1357	else if (errno)
1358	  {
1359	    DBG (3, "read_option: option `%s': can't parse parameter `%s' "
1360		 "(%s)\n", option_string, word, strerror (errno));
1361	    return SANE_STATUS_INVAL;
1362	  }
1363	else
1364	  {
1365	    DBG (3, "read_option: set option `%s' to %d\n", option_string,
1366		 int_value);
1367	    *(SANE_Int *) value = int_value;
1368	  }
1369	break;
1370      }
1371    case param_fixed:
1372      {
1373	double double_value;
1374	SANE_Fixed fixed_value;
1375
1376	cp = sanei_config_get_string (cp, &word);
1377	if (!word)
1378	  return SANE_STATUS_INVAL;
1379	errno = 0;
1380	double_value = strtod (word, &end);
1381	if (end == word)
1382	  {
1383	    DBG (3, "read_option: option `%s' requires parameter\n",
1384		 option_string);
1385	    return SANE_STATUS_INVAL;
1386	  }
1387	else if (errno)
1388	  {
1389	    DBG (3, "read_option: option `%s': can't parse parameter `%s' "
1390		 "(%s)\n", option_string, word, strerror (errno));
1391	    return SANE_STATUS_INVAL;
1392	  }
1393	else
1394	  {
1395	    DBG (3, "read_option: set option `%s' to %.0f\n", option_string,
1396		 double_value);
1397	    fixed_value = SANE_FIX (double_value);
1398	    *(SANE_Fixed *) value = fixed_value;
1399	  }
1400	break;
1401      }
1402    case param_string:
1403      {
1404	cp = sanei_config_get_string (cp, &word);
1405	if (!word)
1406	  return SANE_STATUS_INVAL;
1407	if (strlen (word) == 0)
1408	  {
1409	    DBG (3, "read_option: option `%s' requires parameter\n",
1410		 option_string);
1411	    return SANE_STATUS_INVAL;
1412	  }
1413	else
1414	  {
1415	    DBG (3, "read_option: set option `%s' to `%s'\n", option_string,
1416		 word);
1417	    if (*(SANE_String *) value)
1418	      free (*(SANE_String *) value);
1419	    *(SANE_String *) value = strdup (word);
1420	    if (!*(SANE_String *) value)
1421	      return SANE_STATUS_NO_MEM;
1422	  }
1423	break;
1424      }
1425    default:
1426      DBG (1, "read_option: unknown param_type %d\n", p_type);
1427      return SANE_STATUS_INVAL;
1428    }				/* switch */
1429
1430  if (word)
1431    free (word);
1432  return SANE_STATUS_GOOD;
1433}
1434
1435static SANE_Status
1436reader_process (Test_Device * test_device, SANE_Int fd)
1437{
1438  SANE_Status status;
1439  size_t byte_count = 0;
1440  size_t bytes_total;
1441  SANE_Byte *buffer = 0;
1442  ssize_t bytes_written = 0;
1443  size_t buffer_size = 0, write_count = 0;
1444
1445  DBG (2, "(child) reader_process: test_device=%p, fd=%d\n",
1446       (void *) test_device, fd);
1447
1448  bytes_total = (size_t) test_device->lines * (size_t) test_device->bytes_per_line;
1449  status = init_picture_buffer (test_device, &buffer, &buffer_size);
1450  if (status != SANE_STATUS_GOOD)
1451    return status;
1452
1453  DBG (2, "(child) reader_process: buffer=%p, buffersize=%lu\n",
1454       (void *) buffer, (u_long) buffer_size);
1455
1456  while (byte_count < bytes_total)
1457    {
1458      if (write_count == 0)
1459	{
1460	  write_count = buffer_size;
1461	  if (byte_count + (size_t) write_count > bytes_total)
1462	    write_count = (size_t) bytes_total - (size_t) byte_count;
1463
1464	  if (test_device->val[opt_read_delay].w == SANE_TRUE)
1465	    usleep ((useconds_t) test_device->val[opt_read_delay_duration].w);
1466	}
1467      bytes_written = write (fd, buffer, write_count);
1468      if (bytes_written < 0)
1469	{
1470	  DBG (1, "(child) reader_process: write returned %s\n",
1471	       strerror (errno));
1472	  return SANE_STATUS_IO_ERROR;
1473	}
1474      byte_count += (size_t) bytes_written;
1475      DBG (4, "(child) reader_process: wrote %ld bytes of %lu (%zu total)\n",
1476	   bytes_written, write_count, byte_count);
1477      write_count -= (size_t) bytes_written;
1478    }
1479
1480  free (buffer);
1481
1482  if (sanei_thread_is_forked ())
1483    {
1484	  DBG (4, "(child) reader_process: finished,  wrote %zu bytes, expected %zu "
1485       "bytes, now waiting\n", byte_count, bytes_total);
1486	  while (SANE_TRUE)
1487	    sleep (10);
1488	  DBG (4, "(child) reader_process: this should have never happened...");
1489	  close (fd);
1490    }
1491  else
1492    {
1493	  DBG (4, "(child) reader_process: finished,  wrote %zu bytes, expected %zu "
1494       "bytes\n", byte_count, bytes_total);
1495    }
1496  return SANE_STATUS_GOOD;
1497}
1498
1499/*
1500 * this code either runs in child or thread context...
1501 */
1502static int
1503reader_task (void *data)
1504{
1505  SANE_Status status;
1506  struct SIGACTION act;
1507  struct Test_Device *test_device = (struct Test_Device *) data;
1508
1509  DBG (2, "reader_task started\n");
1510  if (sanei_thread_is_forked ())
1511    {
1512      DBG (3, "reader_task started (forked)\n");
1513      close (test_device->pipe);
1514      test_device->pipe = -1;
1515
1516    }
1517  else
1518    {
1519      DBG (3, "reader_task started (as thread)\n");
1520    }
1521
1522  memset (&act, 0, sizeof (act));
1523  sigaction (SIGTERM, &act, 0);
1524
1525  status = reader_process (test_device, test_device->reader_fds);
1526  DBG (2, "(child) reader_task: reader_process finished (%s)\n",
1527       sane_strstatus (status));
1528  return (int) status;
1529}
1530
1531static SANE_Status
1532finish_pass (Test_Device * test_device)
1533{
1534  SANE_Status return_status = SANE_STATUS_GOOD;
1535
1536  DBG (2, "finish_pass: test_device=%p\n", (void *) test_device);
1537  test_device->scanning = SANE_FALSE;
1538  if (test_device->pipe >= 0)
1539    {
1540      DBG (2, "finish_pass: closing pipe\n");
1541      close (test_device->pipe);
1542      DBG (2, "finish_pass: pipe closed\n");
1543      test_device->pipe = -1;
1544    }
1545  if (sanei_thread_is_valid (test_device->reader_pid))
1546    {
1547      int status;
1548      SANE_Pid pid;
1549
1550      DBG (2, "finish_pass: terminating reader process %ld\n",
1551	   (long) test_device->reader_pid);
1552      sanei_thread_kill (test_device->reader_pid);
1553      pid = sanei_thread_waitpid (test_device->reader_pid, &status);
1554      if (!sanei_thread_is_valid (pid))
1555	{
1556	  DBG (1,
1557	       "finish_pass: sanei_thread_waitpid failed, already terminated? (%s)\n",
1558	       strerror (errno));
1559	}
1560      else
1561	{
1562	  DBG (2, "finish_pass: reader process terminated with status: %s\n",
1563	       sane_strstatus (status));
1564	}
1565      sanei_thread_invalidate (test_device->reader_pid);
1566    }
1567  /* this happens when running in thread context... */
1568  if (test_device->reader_fds >= 0)
1569    {
1570      DBG (2, "finish_pass: closing reader pipe\n");
1571      close (test_device->reader_fds);
1572      DBG (2, "finish_pass: reader pipe closed\n");
1573      test_device->reader_fds = -1;
1574    }
1575  return return_status;
1576}
1577
1578static void
1579print_options (Test_Device * test_device)
1580{
1581  SANE_Option_Descriptor *od;
1582  SANE_Word option_number;
1583  SANE_Char caps[1024];
1584
1585  for (option_number = 0; option_number < num_options; option_number++)
1586    {
1587      od = &test_device->opt[option_number];
1588      DBG (0, "-----> number: %d\n", option_number);
1589      DBG (0, "         name: `%s'\n", od->name);
1590      DBG (0, "        title: `%s'\n", od->title);
1591      DBG (0, "  description: `%s'\n", od->desc);
1592      DBG (0, "         type: %s\n",
1593	   od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" :
1594	   od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" :
1595	   od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" :
1596	   od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" :
1597	   od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" :
1598	   od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown");
1599      DBG (0, "         unit: %s\n",
1600	   od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" :
1601	   od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" :
1602	   od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" :
1603	   od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" :
1604	   od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" :
1605	   od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" :
1606	   od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" :
1607	   "unknown");
1608      DBG (0, "         size: %d\n", od->size);
1609      caps[0] = '\0';
1610      if (od->cap & SANE_CAP_SOFT_SELECT)
1611	strcat (caps, "SANE_CAP_SOFT_SELECT ");
1612      if (od->cap & SANE_CAP_HARD_SELECT)
1613	strcat (caps, "SANE_CAP_HARD_SELECT ");
1614      if (od->cap & SANE_CAP_SOFT_DETECT)
1615	strcat (caps, "SANE_CAP_SOFT_DETECT ");
1616      if (od->cap & SANE_CAP_EMULATED)
1617	strcat (caps, "SANE_CAP_EMULATED ");
1618      if (od->cap & SANE_CAP_AUTOMATIC)
1619	strcat (caps, "SANE_CAP_AUTOMATIC ");
1620      if (od->cap & SANE_CAP_INACTIVE)
1621	strcat (caps, "SANE_CAP_INACTIVE ");
1622      if (od->cap & SANE_CAP_ADVANCED)
1623	strcat (caps, "SANE_CAP_ADVANCED ");
1624      DBG (0, " capabilities: %s\n", caps);
1625      DBG (0, "constraint type: %s\n",
1626	   od->constraint_type == SANE_CONSTRAINT_NONE ?
1627	   "SANE_CONSTRAINT_NONE" :
1628	   od->constraint_type == SANE_CONSTRAINT_RANGE ?
1629	   "SANE_CONSTRAINT_RANGE" :
1630	   od->constraint_type == SANE_CONSTRAINT_WORD_LIST ?
1631	   "SANE_CONSTRAINT_WORD_LIST" :
1632	   od->constraint_type == SANE_CONSTRAINT_STRING_LIST ?
1633	   "SANE_CONSTRAINT_STRING_LIST" : "unknown");
1634    }
1635}
1636
1637/***************************** SANE API ****************************/
1638
1639
1640SANE_Status
1641sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_unused__ authorize)
1642{
1643  FILE *fp;
1644  SANE_Int linenumber;
1645  SANE_Char line[PATH_MAX], *word = NULL;
1646  SANE_String_Const cp;
1647  SANE_Device *sane_device;
1648  Test_Device *test_device, *previous_device;
1649  SANE_Int num;
1650
1651  DBG_INIT ();
1652  sanei_thread_init ();
1653
1654  test_device = 0;
1655  previous_device = 0;
1656
1657  DBG (1, "sane_init: SANE test backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR,
1658       SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
1659
1660  if (version_code)
1661    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
1662
1663  if (inited)
1664    DBG (3, "sane_init: warning: already inited\n");
1665
1666  // Setup initial values of string options. Call free initially in case we've
1667  // already called sane_init and these values are already non-null.
1668  free (init_mode);
1669  init_mode = strdup (SANE_VALUE_SCAN_MODE_GRAY);
1670  if (!init_mode)
1671    goto fail;
1672
1673  free (init_three_pass_order);
1674  init_three_pass_order = strdup ("RGB");
1675  if (!init_three_pass_order)
1676    goto fail;
1677
1678  free (init_scan_source);
1679  init_scan_source = strdup ("Flatbed");
1680  if (!init_scan_source)
1681    goto fail;
1682
1683  free (init_test_picture);
1684  init_test_picture = strdup ("Solid black");
1685  if (!init_test_picture)
1686    goto fail;
1687
1688  free (init_read_status_code);
1689  init_read_status_code = strdup ("Default");
1690  if (!init_read_status_code)
1691    goto fail;
1692
1693  free (init_string);
1694  init_string = strdup ("This is the contents of the string option. "
1695    "Fill some more words to see how the frontend behaves.");
1696  if (!init_string)
1697    goto fail;
1698
1699  free (init_string_constraint_string_list);
1700  init_string_constraint_string_list = strdup ("First entry");
1701  if (!init_string_constraint_string_list)
1702    goto fail;
1703
1704  free (init_string_constraint_long_string_list);
1705  init_string_constraint_long_string_list = strdup ("First entry");
1706  if (!init_string_constraint_long_string_list)
1707    goto fail;
1708
1709  fp = sanei_config_open (TEST_CONFIG_FILE);
1710  if (fp)
1711    {
1712      linenumber = 0;
1713      DBG (4, "sane_init: reading config file `%s'\n", TEST_CONFIG_FILE);
1714      while (sanei_config_read (line, sizeof (line), fp))
1715	{
1716	  if (word)
1717	    free (word);
1718	  word = NULL;
1719	  linenumber++;
1720
1721	  cp = sanei_config_get_string (line, &word);
1722	  if (!word || cp == line)
1723	    {
1724	      DBG (5,
1725		   "sane_init: config file line %3d: ignoring empty line\n",
1726		   linenumber);
1727	      continue;
1728	    }
1729	  if (word[0] == '#')
1730	    {
1731	      DBG (5,
1732		   "sane_init: config file line %3d: ignoring comment line\n",
1733		   linenumber);
1734	      continue;
1735	    }
1736
1737	  DBG (5, "sane_init: config file line %3d: `%s'\n",
1738	       linenumber, line);
1739	  if (read_option (line, "number_of_devices", param_int,
1740			   &init_number_of_devices) == SANE_STATUS_GOOD)
1741	    continue;
1742	  if (read_option (line, "mode", param_string,
1743			   &init_mode) == SANE_STATUS_GOOD)
1744	    continue;
1745	  if (read_option (line, "hand-scanner", param_bool,
1746			   &init_hand_scanner) == SANE_STATUS_GOOD)
1747	    continue;
1748	  if (read_option (line, "three-pass", param_bool,
1749			   &init_three_pass) == SANE_STATUS_GOOD)
1750	    continue;
1751	  if (read_option (line, "three-pass-order", param_string,
1752			   &init_three_pass_order) == SANE_STATUS_GOOD)
1753	    continue;
1754	  if (read_option (line, "resolution_min", param_fixed,
1755			   &resolution_range.min) == SANE_STATUS_GOOD)
1756	    continue;
1757	  if (read_option (line, "resolution_max", param_fixed,
1758			   &resolution_range.max) == SANE_STATUS_GOOD)
1759	    continue;
1760	  if (read_option (line, "resolution_quant", param_fixed,
1761			   &resolution_range.quant) == SANE_STATUS_GOOD)
1762	    continue;
1763	  if (read_option (line, "resolution", param_fixed,
1764			   &init_resolution) == SANE_STATUS_GOOD)
1765	    continue;
1766	  if (read_option (line, "depth", param_int,
1767			   &init_depth) == SANE_STATUS_GOOD)
1768	    continue;
1769	  if (read_option (line, "scan-source", param_string,
1770			   &init_scan_source) == SANE_STATUS_GOOD)
1771	    continue;
1772	  if (read_option (line, "test-picture", param_string,
1773			   &init_test_picture) == SANE_STATUS_GOOD)
1774	    continue;
1775	  if (read_option (line, "invert-endianess", param_bool,
1776			   &init_invert_endianess) == SANE_STATUS_GOOD)
1777	    continue;
1778	  if (read_option (line, "read-limit", param_bool,
1779			   &init_read_limit) == SANE_STATUS_GOOD)
1780	    continue;
1781	  if (read_option (line, "read-limit-size", param_int,
1782			   &init_read_limit_size) == SANE_STATUS_GOOD)
1783	    continue;
1784	  if (read_option (line, "read-delay", param_bool,
1785			   &init_read_delay) == SANE_STATUS_GOOD)
1786	    continue;
1787	  if (read_option (line, "read-delay-duration", param_int,
1788			   &init_read_delay_duration) == SANE_STATUS_GOOD)
1789	    continue;
1790	  if (read_option (line, "read-status-code", param_string,
1791			   &init_read_status_code) == SANE_STATUS_GOOD)
1792	    continue;
1793	  if (read_option (line, "ppl-loss", param_int,
1794			   &init_ppl_loss) == SANE_STATUS_GOOD)
1795	    continue;
1796	  if (read_option (line, "fuzzy-parameters", param_bool,
1797			   &init_fuzzy_parameters) == SANE_STATUS_GOOD)
1798	    continue;
1799	  if (read_option (line, "non-blocking", param_bool,
1800			   &init_non_blocking) == SANE_STATUS_GOOD)
1801	    continue;
1802	  if (read_option (line, "select-fd", param_bool,
1803			   &init_select_fd) == SANE_STATUS_GOOD)
1804	    continue;
1805	  if (read_option (line, "enable-test-options", param_bool,
1806			   &init_enable_test_options) == SANE_STATUS_GOOD)
1807	    continue;
1808	  if (read_option (line, "geometry_min", param_fixed,
1809			   &geometry_range.min) == SANE_STATUS_GOOD)
1810	    continue;
1811	  if (read_option (line, "geometry_max", param_fixed,
1812			   &geometry_range.max) == SANE_STATUS_GOOD)
1813	    continue;
1814	  if (read_option (line, "geometry_quant", param_fixed,
1815			   &geometry_range.quant) == SANE_STATUS_GOOD)
1816	    continue;
1817	  if (read_option (line, "tl_x", param_fixed,
1818			   &init_tl_x) == SANE_STATUS_GOOD)
1819	    continue;
1820	  if (read_option (line, "tl_y", param_fixed,
1821			   &init_tl_y) == SANE_STATUS_GOOD)
1822	    continue;
1823	  if (read_option (line, "br_x", param_fixed,
1824			   &init_br_x) == SANE_STATUS_GOOD)
1825	    continue;
1826	  if (read_option (line, "br_y", param_fixed,
1827			   &init_br_y) == SANE_STATUS_GOOD)
1828	    continue;
1829
1830	  DBG (3, "sane-init: I don't know how to handle option `%s'\n",
1831	       word);
1832	}			/* while */
1833      if (word)
1834	free (word);
1835      fclose (fp);
1836    }				/* if */
1837  else
1838    {
1839      DBG (3, "sane_init: couldn't find config file (%s), using default "
1840	   "settings\n", TEST_CONFIG_FILE);
1841    }
1842
1843  /* create devices */
1844  sane_device_list =
1845    malloc ((size_t) (init_number_of_devices + 1) * sizeof (sane_device));
1846  if (!sane_device_list)
1847    goto fail;
1848  for (num = 0; num < init_number_of_devices; num++)
1849    {
1850      SANE_Char number_string[PATH_MAX];
1851
1852      test_device = calloc (sizeof (*test_device), 1);
1853      if (!test_device)
1854	goto fail_device;
1855      test_device->sane.vendor = "Noname";
1856      test_device->sane.type = "virtual device";
1857      test_device->sane.model = "frontend-tester";
1858      snprintf (number_string, sizeof (number_string), "%d", num);
1859      number_string[sizeof (number_string) - 1] = '\0';
1860      test_device->name = strdup (number_string);
1861      if (!test_device->name)
1862	goto fail_name;
1863      test_device->sane.name = test_device->name;
1864      if (previous_device)
1865	previous_device->next = test_device;
1866      previous_device = test_device;
1867      if (num == 0)
1868	first_test_device = test_device;
1869      sane_device_list[num] = &test_device->sane;
1870      test_device->open = SANE_FALSE;
1871      test_device->eof = SANE_FALSE;
1872      test_device->scanning = SANE_FALSE;
1873      test_device->cancelled = SANE_FALSE;
1874      test_device->options_initialized = SANE_FALSE;
1875      sanei_thread_initialize (test_device->reader_pid);
1876      test_device->pipe = -1;
1877      DBG (4, "sane_init: new device: `%s' is a %s %s %s\n",
1878	   test_device->sane.name, test_device->sane.vendor,
1879	   test_device->sane.model, test_device->sane.type);
1880    }
1881  test_device->next = 0;
1882  sane_device_list[num] = 0;
1883  srand ((unsigned int) time (NULL));
1884  random_factor = ((double) rand ()) / RAND_MAX + 0.5;
1885  inited = SANE_TRUE;
1886  return SANE_STATUS_GOOD;
1887
1888fail_name:
1889  // test_device refers to the last device we were creating, which has not
1890  // yet been added to the linked list of devices.
1891  free (test_device);
1892fail_device:
1893  // Now, iterate through the linked list of devices to clean up any successful
1894  // devices.
1895  test_device = first_test_device;
1896  while (test_device)
1897    {
1898      previous_device = test_device;
1899      test_device = test_device->next;
1900      cleanup_test_device (previous_device);
1901    }
1902  free (sane_device_list);
1903fail:
1904  cleanup_initial_string_values ();
1905  return SANE_STATUS_NO_MEM;
1906}
1907
1908void
1909sane_exit (void)
1910{
1911  Test_Device *test_device, *previous_device;
1912
1913  DBG (2, "sane_exit\n");
1914  if (!inited)
1915    {
1916      DBG (1, "sane_exit: not inited, call sane_init() first\n");
1917      return;
1918    }
1919
1920  test_device = first_test_device;
1921  while (test_device)
1922    {
1923      DBG (4, "sane_exit: freeing device %s\n", test_device->name);
1924      previous_device = test_device;
1925      test_device = test_device->next;
1926      cleanup_test_device (previous_device);
1927    }
1928  DBG (4, "sane_exit: freeing device list\n");
1929  if (sane_device_list)
1930    free (sane_device_list);
1931  sane_device_list = NULL;
1932  first_test_device = NULL;
1933
1934  cleanup_initial_string_values ();
1935  inited = SANE_FALSE;
1936  return;
1937}
1938
1939
1940SANE_Status
1941sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1942{
1943
1944  DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n",
1945       (void *) device_list, local_only);
1946  if (!inited)
1947    {
1948      DBG (1, "sane_get_devices: not inited, call sane_init() first\n");
1949      return SANE_STATUS_INVAL;
1950    }
1951
1952  if (!device_list)
1953    {
1954      DBG (1, "sane_get_devices: device_list == 0\n");
1955      return SANE_STATUS_INVAL;
1956    }
1957  *device_list = (const SANE_Device **) sane_device_list;
1958  return SANE_STATUS_GOOD;
1959}
1960
1961SANE_Status
1962sane_open (SANE_String_Const devicename, SANE_Handle * handle)
1963{
1964  Test_Device *test_device = first_test_device;
1965  SANE_Status status;
1966
1967  DBG (2, "sane_open: devicename = \"%s\", handle=%p\n",
1968       devicename, (void *) handle);
1969  if (!inited)
1970    {
1971      DBG (1, "sane_open: not inited, call sane_init() first\n");
1972      return SANE_STATUS_INVAL;
1973    }
1974
1975  if (!handle)
1976    {
1977      DBG (1, "sane_open: handle == 0\n");
1978      return SANE_STATUS_INVAL;
1979    }
1980
1981  if (!devicename || strlen (devicename) == 0)
1982    {
1983      DBG (2, "sane_open: device name NULL or empty\n");
1984    }
1985  else
1986    {
1987      for (test_device = first_test_device; test_device;
1988	   test_device = test_device->next)
1989	{
1990	  if (strcmp (devicename, test_device->name) == 0)
1991	    break;
1992	}
1993    }
1994  if (!test_device)
1995    {
1996      DBG (1, "sane_open: device `%s' not found\n", devicename);
1997      return SANE_STATUS_INVAL;
1998    }
1999  if (test_device->open)
2000    {
2001      DBG (1, "sane_open: device `%s' already open\n", devicename);
2002      return SANE_STATUS_DEVICE_BUSY;
2003    }
2004  DBG (2, "sane_open: opening device `%s', handle = %p\n", test_device->name,
2005       (void *) test_device);
2006  test_device->open = SANE_TRUE;
2007  *handle = test_device;
2008
2009  if (!test_device->options_initialized) {
2010    status = init_options (test_device);
2011    if (status != SANE_STATUS_GOOD)
2012      return status;
2013    test_device->options_initialized = SANE_TRUE;
2014  }
2015
2016  test_device->open = SANE_TRUE;
2017  test_device->scanning = SANE_FALSE;
2018  test_device->cancelled = SANE_FALSE;
2019  test_device->eof = SANE_FALSE;
2020  test_device->bytes_total = 0;
2021  test_device->pass = 0;
2022  test_device->number_of_scans = 0;
2023
2024  return SANE_STATUS_GOOD;
2025}
2026
2027void
2028sane_close (SANE_Handle handle)
2029{
2030  Test_Device *test_device = handle;
2031
2032  DBG (2, "sane_close: handle=%p\n", (void *) handle);
2033  if (!inited)
2034    {
2035      DBG (1, "sane_close: not inited, call sane_init() first\n");
2036      return;
2037    }
2038
2039  if (!check_handle (handle))
2040    {
2041      DBG (1, "sane_close: handle %p unknown\n", (void *) handle);
2042      return;
2043    }
2044  if (!test_device->open)
2045    {
2046      DBG (1, "sane_close: handle %p not open\n", (void *) handle);
2047      return;
2048    }
2049  test_device->open = SANE_FALSE;
2050  return;
2051}
2052
2053const SANE_Option_Descriptor *
2054sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2055{
2056  Test_Device *test_device = handle;
2057
2058  DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n",
2059       (void *) handle, option);
2060  if (!inited)
2061    {
2062      DBG (1, "sane_get_option_descriptor: not inited, call sane_init() "
2063	   "first\n");
2064      return 0;
2065    }
2066
2067  if (!check_handle (handle))
2068    {
2069      DBG (1, "sane_get_option_descriptor: handle %p unknown\n",
2070	   (void *) handle);
2071      return 0;
2072    }
2073  if (!test_device->open)
2074    {
2075      DBG (1, "sane_get_option_descriptor: not open\n");
2076      return 0;
2077    }
2078  if (option < 0 || option >= num_options)
2079    {
2080      DBG (3, "sane_get_option_descriptor: option < 0 || "
2081	   "option > num_options\n");
2082      return 0;
2083    }
2084
2085  test_device->loaded[option] = 1;
2086
2087  return &test_device->opt[option];
2088}
2089
2090SANE_Status
2091sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
2092		     void *value, SANE_Int * info)
2093{
2094  Test_Device *test_device = handle;
2095  SANE_Int myinfo = 0;
2096  SANE_Status status;
2097
2098  DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
2099       (void *) handle, option, action, (void *) value, (void *) info);
2100  if (!inited)
2101    {
2102      DBG (1, "sane_control_option: not inited, call sane_init() first\n");
2103      return SANE_STATUS_INVAL;
2104    }
2105
2106  if (!check_handle (handle))
2107    {
2108      DBG (1, "sane_control_option: handle %p unknown\n", (void *) handle);
2109      return SANE_STATUS_INVAL;
2110    }
2111  if (!test_device->open)
2112    {
2113      DBG (1, "sane_control_option: not open\n");
2114      return SANE_STATUS_INVAL;
2115    }
2116  if (test_device->scanning)
2117    {
2118      DBG (1, "sane_control_option: is scanning\n");
2119      return SANE_STATUS_INVAL;
2120    }
2121  if (option < 0 || option >= num_options)
2122    {
2123      DBG (1, "sane_control_option: option < 0 || option > num_options\n");
2124      return SANE_STATUS_INVAL;
2125    }
2126
2127  if (!test_device->loaded[option])
2128    {
2129      DBG (1, "sane_control_option: option not loaded\n");
2130      return SANE_STATUS_INVAL;
2131    }
2132
2133  if (!SANE_OPTION_IS_ACTIVE (test_device->opt[option].cap))
2134    {
2135      DBG (1, "sane_control_option: option is inactive\n");
2136      return SANE_STATUS_INVAL;
2137    }
2138
2139  if (test_device->opt[option].type == SANE_TYPE_GROUP)
2140    {
2141      DBG (1, "sane_control_option: option is a group\n");
2142      return SANE_STATUS_INVAL;
2143    }
2144
2145  switch (action)
2146    {
2147    case SANE_ACTION_SET_AUTO:
2148      if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap))
2149	{
2150	  DBG (1, "sane_control_option: option is not setable\n");
2151	  return SANE_STATUS_INVAL;
2152	}
2153      if (!(test_device->opt[option].cap & SANE_CAP_AUTOMATIC))
2154	{
2155	  DBG (1, "sane_control_option: option is not automatically "
2156	       "setable\n");
2157	  return SANE_STATUS_INVAL;
2158	}
2159      switch (option)
2160	{
2161	case opt_bool_soft_select_soft_detect_auto:
2162	  test_device->val[option].w = SANE_TRUE;
2163	  DBG (4, "sane_control_option: set option %d (%s) automatically "
2164	       "to %s\n", option, test_device->opt[option].name,
2165	       test_device->val[option].w == SANE_TRUE ? "true" : "false");
2166	  break;
2167
2168	default:
2169	  DBG (1, "sane_control_option: trying to automatically set "
2170	       "unexpected option\n");
2171	  return SANE_STATUS_INVAL;
2172	}
2173      break;
2174
2175    case SANE_ACTION_SET_VALUE:
2176      if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap))
2177	{
2178	  DBG (1, "sane_control_option: option is not setable\n");
2179	  return SANE_STATUS_INVAL;
2180	}
2181      status = sanei_constrain_value (&test_device->opt[option],
2182				      value, &myinfo);
2183      if (status != SANE_STATUS_GOOD)
2184	{
2185	  DBG (3, "sane_control_option: sanei_constrain_value returned %s\n",
2186	       sane_strstatus (status));
2187	  return status;
2188	}
2189      switch (option)
2190	{
2191	case opt_tl_x:		/* Fixed with parameter reloading */
2192	case opt_tl_y:
2193	case opt_br_x:
2194	case opt_br_y:
2195	case opt_resolution:
2196	  if (test_device->val[option].w == *(SANE_Fixed *) value)
2197	    {
2198	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2199		   option, test_device->opt[option].name);
2200	      break;
2201	    }
2202	  test_device->val[option].w = *(SANE_Fixed *) value;
2203	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2204	  DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n",
2205	       option, test_device->opt[option].name,
2206	       SANE_UNFIX (*(SANE_Fixed *) value),
2207	       test_device->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi");
2208	  break;
2209	case opt_fixed:	/* Fixed */
2210	case opt_fixed_constraint_range:
2211	  if (test_device->val[option].w == *(SANE_Fixed *) value)
2212	    {
2213	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2214		   option, test_device->opt[option].name);
2215	      break;
2216	    }
2217	  test_device->val[option].w = *(SANE_Fixed *) value;
2218	  DBG (4, "sane_control_option: set option %d (%s) to %.0f\n",
2219	       option, test_device->opt[option].name,
2220	       SANE_UNFIX (*(SANE_Fixed *) value));
2221	  break;
2222	case opt_read_limit_size:	/* Int */
2223	case opt_ppl_loss:
2224	case opt_read_delay_duration:
2225	case opt_int:
2226	case opt_int_constraint_range:
2227	  if (test_device->val[option].w == *(SANE_Int *) value)
2228	    {
2229	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2230		   option, test_device->opt[option].name);
2231	      break;
2232	    }
2233	  test_device->val[option].w = *(SANE_Int *) value;
2234	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2235	       option, test_device->opt[option].name, *(SANE_Int *) value);
2236	  break;
2237	case opt_int_inexact:
2238	  if (test_device->val[option].w == *(SANE_Int *) value)
2239	    {
2240	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2241		   option, test_device->opt[option].name);
2242	      break;
2243	    }
2244          *(SANE_Int *) value += 1;
2245	  test_device->val[option].w = *(SANE_Int *) value;
2246          myinfo |= SANE_INFO_INEXACT;
2247	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2248	       option, test_device->opt[option].name, *(SANE_Int *) value);
2249	  break;
2250	case opt_fuzzy_parameters:	/* Bool with parameter reloading */
2251	  if (test_device->val[option].w == *(SANE_Bool *) value)
2252	    {
2253	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2254		   option, test_device->opt[option].name);
2255	      break;
2256	    }
2257	  test_device->val[option].w = *(SANE_Bool *) value;
2258	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2259	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2260	       option, test_device->opt[option].name,
2261	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2262	  break;
2263	case opt_invert_endianess:	/* Bool */
2264	case opt_non_blocking:
2265	case opt_select_fd:
2266	case opt_bool_soft_select_soft_detect:
2267	case opt_bool_soft_select_soft_detect_auto:
2268	case opt_bool_soft_select_soft_detect_emulated:
2269	  if (test_device->val[option].w == *(SANE_Bool *) value)
2270	    {
2271	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2272		   option, test_device->opt[option].name);
2273	      break;
2274	    }
2275	  test_device->val[option].w = *(SANE_Bool *) value;
2276	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2277	       option, test_device->opt[option].name,
2278	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2279	  break;
2280	case opt_depth:	/* Word list with parameter and options reloading */
2281	  if (test_device->val[option].w == *(SANE_Int *) value)
2282	    {
2283	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2284		   option, test_device->opt[option].name);
2285	      break;
2286	    }
2287	  test_device->val[option].w = *(SANE_Int *) value;
2288	  if (test_device->val[option].w == 16)
2289	    test_device->opt[opt_invert_endianess].cap &= ~SANE_CAP_INACTIVE;
2290	  else
2291	    test_device->opt[opt_invert_endianess].cap |= SANE_CAP_INACTIVE;
2292
2293	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2294	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2295	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2296	       option, test_device->opt[option].name, *(SANE_Int *) value);
2297	  break;
2298	case opt_three_pass_order:	/* String list with parameter reload */
2299	  if (strcmp (test_device->val[option].s, value) == 0)
2300	    {
2301	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2302		   option, test_device->opt[option].name);
2303	      break;
2304	    }
2305	  strcpy (test_device->val[option].s, (SANE_String) value);
2306	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2307	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2308	       option, test_device->opt[option].name, (SANE_String) value);
2309	  break;
2310	case opt_int_constraint_word_list:	/* Word list */
2311	case opt_fixed_constraint_word_list:
2312	  if (test_device->val[option].w == *(SANE_Int *) value)
2313	    {
2314	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2315		   option, test_device->opt[option].name);
2316	      break;
2317	    }
2318	  test_device->val[option].w = *(SANE_Int *) value;
2319	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2320	       option, test_device->opt[option].name, *(SANE_Int *) value);
2321	  break;
2322	case opt_read_status_code:	/* String (list) */
2323	case opt_test_picture:
2324	case opt_string:
2325	case opt_string_constraint_string_list:
2326	case opt_string_constraint_long_string_list:
2327	case opt_scan_source:
2328	  if (strcmp (test_device->val[option].s, value) == 0)
2329	    {
2330	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2331		   option, test_device->opt[option].name);
2332	      break;
2333	    }
2334	  strcpy (test_device->val[option].s, (SANE_String) value);
2335	  DBG (4, "sane_control_option: set option %d (%s) to `%s'\n",
2336	       option, test_device->opt[option].name, (SANE_String) value);
2337	  break;
2338	case opt_int_array:	/* Word array */
2339	case opt_int_array_constraint_range:
2340	case opt_gamma_red:
2341	case opt_gamma_green:
2342	case opt_gamma_blue:
2343	case opt_gamma_all:
2344	case opt_int_array_constraint_word_list:
2345	  memcpy (test_device->val[option].wa, value,
2346		  (size_t) test_device->opt[option].size);
2347	  DBG (4, "sane_control_option: set option %d (%s) to %p\n",
2348	       option, test_device->opt[option].name, (void *) value);
2349	  if (option == opt_gamma_all) {
2350	      print_gamma_table(gamma_all, GAMMA_ALL_SIZE);
2351	  }
2352	  if (option == opt_gamma_red) {
2353	      print_gamma_table(gamma_red, GAMMA_RED_SIZE);
2354	  }
2355	  break;
2356	  /* options with side-effects */
2357	case opt_print_options:
2358	  DBG (4, "sane_control_option: set option %d (%s)\n",
2359	       option, test_device->opt[option].name);
2360	  print_options (test_device);
2361	  break;
2362	case opt_button:
2363	  DBG (0, "Yes! You pressed me!\n");
2364	  DBG (4, "sane_control_option: set option %d (%s)\n",
2365	       option, test_device->opt[option].name);
2366	  break;
2367	case opt_mode:
2368	  if (strcmp (test_device->val[option].s, value) == 0)
2369	    {
2370	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2371		   option, test_device->opt[option].name);
2372	      break;
2373	    }
2374	  strcpy (test_device->val[option].s, (SANE_String) value);
2375	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2376	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2377	  if (strcmp (test_device->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
2378	    {
2379	      test_device->opt[opt_three_pass].cap &= ~SANE_CAP_INACTIVE;
2380	      if (test_device->val[opt_three_pass].w == SANE_TRUE)
2381		test_device->opt[opt_three_pass_order].cap
2382		  &= ~SANE_CAP_INACTIVE;
2383	    }
2384	  else
2385	    {
2386	      test_device->opt[opt_three_pass].cap |= SANE_CAP_INACTIVE;
2387	      test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE;
2388	    }
2389	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2390	       option, test_device->opt[option].name, (SANE_String) value);
2391	  break;
2392	case opt_three_pass:
2393	  if (test_device->val[option].w == *(SANE_Bool *) value)
2394	    {
2395	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2396		   option, test_device->opt[option].name);
2397	      break;
2398	    }
2399	  test_device->val[option].w = *(SANE_Bool *) value;
2400	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2401	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2402	  if (test_device->val[option].w == SANE_TRUE)
2403	    test_device->opt[opt_three_pass_order].cap &= ~SANE_CAP_INACTIVE;
2404	  else
2405	    test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE;
2406	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2407	       option, test_device->opt[option].name,
2408	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2409	  break;
2410	case opt_hand_scanner:
2411	  if (test_device->val[option].w == *(SANE_Bool *) value)
2412	    {
2413	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2414		   option, test_device->opt[option].name);
2415	      break;
2416	    }
2417	  test_device->val[option].w = *(SANE_Bool *) value;
2418	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2419	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2420	  if (test_device->val[option].w == SANE_TRUE)
2421	    {
2422	      test_device->opt[opt_tl_x].cap |= SANE_CAP_INACTIVE;
2423	      test_device->opt[opt_tl_y].cap |= SANE_CAP_INACTIVE;
2424	      test_device->opt[opt_br_x].cap |= SANE_CAP_INACTIVE;
2425	      test_device->opt[opt_br_y].cap |= SANE_CAP_INACTIVE;
2426	    }
2427	  else
2428	    {
2429	      test_device->opt[opt_tl_x].cap &= ~SANE_CAP_INACTIVE;
2430	      test_device->opt[opt_tl_y].cap &= ~SANE_CAP_INACTIVE;
2431	      test_device->opt[opt_br_x].cap &= ~SANE_CAP_INACTIVE;
2432	      test_device->opt[opt_br_y].cap &= ~SANE_CAP_INACTIVE;
2433	    }
2434	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2435	       option, test_device->opt[option].name,
2436	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2437	  break;
2438	case opt_read_limit:
2439	  if (test_device->val[option].w == *(SANE_Bool *) value)
2440	    {
2441	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2442		   option, test_device->opt[option].name);
2443	      break;
2444	    }
2445	  test_device->val[option].w = *(SANE_Bool *) value;
2446	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2447	  if (test_device->val[option].w == SANE_TRUE)
2448	    test_device->opt[opt_read_limit_size].cap &= ~SANE_CAP_INACTIVE;
2449	  else
2450	    test_device->opt[opt_read_limit_size].cap |= SANE_CAP_INACTIVE;
2451	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2452	       option, test_device->opt[option].name,
2453	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2454	  break;
2455	case opt_read_delay:
2456	  if (test_device->val[option].w == *(SANE_Bool *) value)
2457	    {
2458	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2459		   option, test_device->opt[option].name);
2460	      break;
2461	    }
2462	  test_device->val[option].w = *(SANE_Bool *) value;
2463	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2464	  if (test_device->val[option].w == SANE_TRUE)
2465	    test_device->opt[opt_read_delay_duration].cap
2466	      &= ~SANE_CAP_INACTIVE;
2467	  else
2468	    test_device->opt[opt_read_delay_duration].cap |=
2469	      SANE_CAP_INACTIVE;
2470	  DBG (4, "sane_control_option: set option %d (%s) to %s\n", option,
2471	       test_device->opt[option].name,
2472	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2473	  break;
2474	case opt_enable_test_options:
2475	  {
2476	    int option_number;
2477	    if (test_device->val[option].w == *(SANE_Bool *) value)
2478	      {
2479		DBG (4, "sane_control_option: option %d (%s) not changed\n",
2480		     option, test_device->opt[option].name);
2481		break;
2482	      }
2483	    test_device->val[option].w = *(SANE_Bool *) value;
2484	    myinfo |= SANE_INFO_RELOAD_OPTIONS;
2485	    for (option_number = opt_bool_soft_select_soft_detect;
2486		 option_number < num_options; option_number++)
2487	      {
2488		if (test_device->opt[option_number].type == SANE_TYPE_GROUP)
2489		  continue;
2490		if (test_device->val[option].w == SANE_TRUE)
2491		  test_device->opt[option_number].cap &= ~SANE_CAP_INACTIVE;
2492		else
2493		  test_device->opt[option_number].cap |= SANE_CAP_INACTIVE;
2494	      }
2495	    DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2496		 option, test_device->opt[option].name,
2497		 *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2498	    break;
2499	  }
2500	default:
2501	  DBG (1, "sane_control_option: trying to set unexpected option\n");
2502	  return SANE_STATUS_INVAL;
2503	}
2504      break;
2505
2506    case SANE_ACTION_GET_VALUE:
2507      switch (option)
2508	{
2509	case opt_num_opts:
2510	  *(SANE_Word *) value = num_options;
2511	  DBG (4, "sane_control_option: get option 0, value = %d\n",
2512	       num_options);
2513	  break;
2514	case opt_tl_x:		/* Fixed options */
2515	case opt_tl_y:
2516	case opt_br_x:
2517	case opt_br_y:
2518	case opt_resolution:
2519	case opt_fixed:
2520	case opt_fixed_constraint_range:
2521	case opt_fixed_constraint_word_list:
2522	  {
2523	    *(SANE_Fixed *) value = test_device->val[option].w;
2524	    DBG (4,
2525		 "sane_control_option: get option %d (%s), value=%.1f %s\n",
2526		 option, test_device->opt[option].name,
2527		 SANE_UNFIX (*(SANE_Fixed *) value),
2528		 test_device->opt[option].unit ==
2529		 SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : "");
2530	    break;
2531	  }
2532	case opt_hand_scanner:	/* Bool options */
2533	case opt_three_pass:
2534	case opt_invert_endianess:
2535	case opt_read_limit:
2536	case opt_read_delay:
2537	case opt_fuzzy_parameters:
2538	case opt_non_blocking:
2539	case opt_select_fd:
2540	case opt_bool_soft_select_soft_detect:
2541	case opt_bool_hard_select_soft_detect:
2542	case opt_bool_soft_detect:
2543	case opt_enable_test_options:
2544	case opt_bool_soft_select_soft_detect_emulated:
2545	case opt_bool_soft_select_soft_detect_auto:
2546	  *(SANE_Bool *) value = test_device->val[option].w;
2547	  DBG (4,
2548	       "sane_control_option: get option %d (%s), value=%s\n",
2549	       option, test_device->opt[option].name,
2550	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2551	  break;
2552	case opt_mode:		/* String (list) options */
2553	case opt_three_pass_order:
2554	case opt_read_status_code:
2555	case opt_test_picture:
2556	case opt_string:
2557	case opt_string_constraint_string_list:
2558	case opt_string_constraint_long_string_list:
2559	case opt_scan_source:
2560	  strcpy (value, test_device->val[option].s);
2561	  DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n",
2562	       option, test_device->opt[option].name, (SANE_String) value);
2563	  break;
2564	case opt_depth:	/* Int + word list options */
2565	case opt_read_limit_size:
2566	case opt_ppl_loss:
2567	case opt_read_delay_duration:
2568	case opt_int:
2569        case opt_int_inexact:
2570	case opt_int_constraint_range:
2571	case opt_int_constraint_word_list:
2572	  *(SANE_Int *) value = test_device->val[option].w;
2573	  DBG (4, "sane_control_option: get option %d (%s), value=%d\n",
2574	       option, test_device->opt[option].name, *(SANE_Int *) value);
2575	  break;
2576	case opt_int_array:	/* Int array */
2577	case opt_int_array_constraint_range:
2578	case opt_gamma_red:
2579	case opt_gamma_green:
2580	case opt_gamma_blue:
2581	case opt_gamma_all:
2582	case opt_int_array_constraint_word_list:
2583	  memcpy (value, test_device->val[option].wa,
2584		  (size_t) test_device->opt[option].size);
2585	  DBG (4, "sane_control_option: get option %d (%s), value=%p\n",
2586	       option, test_device->opt[option].name, (void *) value);
2587	  break;
2588	default:
2589	  DBG (1, "sane_control_option: trying to get unexpected option\n");
2590	  return SANE_STATUS_INVAL;
2591	}
2592      break;
2593    default:
2594      DBG (1, "sane_control_option: trying unexpected action %d\n", action);
2595      return SANE_STATUS_INVAL;
2596    }
2597
2598  if (info)
2599    *info = myinfo;
2600
2601  if(myinfo & SANE_INFO_RELOAD_OPTIONS){
2602    SANE_Int i = 0;
2603    for(i=1;i<num_options;i++){
2604      test_device->loaded[i] = 0;
2605    }
2606  }
2607
2608  DBG (4, "sane_control_option: finished, info=%s %s %s \n",
2609       myinfo & SANE_INFO_INEXACT ? "inexact" : "",
2610       myinfo & SANE_INFO_RELOAD_PARAMS ? "reload_parameters" : "",
2611       myinfo & SANE_INFO_RELOAD_OPTIONS ? "reload_options" : "");
2612
2613  return SANE_STATUS_GOOD;
2614}
2615
2616
2617SANE_Status
2618sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2619{
2620  Test_Device *test_device = handle;
2621  SANE_Parameters *p;
2622  double res, tl_x = 0, tl_y = 0, br_x = 0, br_y = 0;
2623  SANE_String text_format, mode;
2624  SANE_Int channels = 1;
2625
2626  DBG (2, "sane_get_parameters: handle=%p, params=%p\n",
2627       (void *) handle, (void *) params);
2628  if (!inited)
2629    {
2630      DBG (1, "sane_get_parameters: not inited, call sane_init() first\n");
2631      return SANE_STATUS_INVAL;
2632    }
2633  if (!check_handle (handle))
2634    {
2635      DBG (1, "sane_get_parameters: handle %p unknown\n", (void *) handle);
2636      return SANE_STATUS_INVAL;
2637    }
2638  if (!test_device->open)
2639    {
2640      DBG (1, "sane_get_parameters: handle %p not open\n", (void *) handle);
2641      return SANE_STATUS_INVAL;
2642    }
2643
2644  res = SANE_UNFIX (test_device->val[opt_resolution].w);
2645  mode = test_device->val[opt_mode].s;
2646  p = &test_device->params;
2647  p->depth = test_device->val[opt_depth].w;
2648
2649  if (test_device->val[opt_hand_scanner].w == SANE_TRUE)
2650    {
2651      tl_x = 0.0;
2652      br_x = 110.0;
2653      tl_y = 0.0;
2654      br_y = 170.0;
2655      p->lines = -1;
2656      test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH);
2657    }
2658  else
2659    {
2660      tl_x = SANE_UNFIX (test_device->val[opt_tl_x].w);
2661      tl_y = SANE_UNFIX (test_device->val[opt_tl_y].w);
2662      br_x = SANE_UNFIX (test_device->val[opt_br_x].w);
2663      br_y = SANE_UNFIX (test_device->val[opt_br_y].w);
2664      if (tl_x > br_x)
2665	swap_double (&tl_x, &br_x);
2666      if (tl_y > br_y)
2667	swap_double (&tl_y, &br_y);
2668      test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH);
2669      if (test_device->lines < 1)
2670	test_device->lines = 1;
2671      p->lines = test_device->lines;
2672      if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE
2673	  && test_device->scanning == SANE_FALSE)
2674	p->lines *= (SANE_Int) random_factor;
2675    }
2676
2677  if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
2678    {
2679      p->format = SANE_FRAME_GRAY;
2680      p->last_frame = SANE_TRUE;
2681    }
2682  else				/* Color */
2683    {
2684      if (test_device->val[opt_three_pass].w == SANE_TRUE)
2685	{
2686	  if (test_device->val[opt_three_pass_order].s[test_device->pass]
2687	      == 'R')
2688	    p->format = SANE_FRAME_RED;
2689	  else if (test_device->val[opt_three_pass_order].s[test_device->pass]
2690		   == 'G')
2691	    p->format = SANE_FRAME_GREEN;
2692	  else
2693	    p->format = SANE_FRAME_BLUE;
2694	  if (test_device->pass > 1)
2695	    p->last_frame = SANE_TRUE;
2696	  else
2697	    p->last_frame = SANE_FALSE;
2698	}
2699      else
2700	{
2701	  p->format = SANE_FRAME_RGB;
2702	  p->last_frame = SANE_TRUE;
2703	}
2704    }
2705
2706  p->pixels_per_line = (SANE_Int) (res * (br_x - tl_x) / MM_PER_INCH);
2707  if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE
2708      && test_device->scanning == SANE_FALSE)
2709    p->pixels_per_line *= (SANE_Int) random_factor;
2710  if (p->pixels_per_line < 1)
2711    p->pixels_per_line = 1;
2712
2713  if (p->format == SANE_FRAME_RGB)
2714    channels = 3;
2715
2716  if (p->depth == 1)
2717    p->bytes_per_line = channels * (int) ((p->pixels_per_line + 7) / 8);
2718  else				/* depth == 8 || depth == 16 */
2719    p->bytes_per_line = channels * p->pixels_per_line * ((p->depth + 7) / 8);
2720
2721  test_device->bytes_per_line = p->bytes_per_line;
2722
2723  p->pixels_per_line -= test_device->val[opt_ppl_loss].w;
2724  if (p->pixels_per_line < 1)
2725    p->pixels_per_line = 1;
2726  test_device->pixels_per_line = p->pixels_per_line;
2727
2728  switch (p->format)
2729    {
2730    case SANE_FRAME_GRAY:
2731      text_format = "gray";
2732      break;
2733    case SANE_FRAME_RGB:
2734      text_format = "rgb";
2735      break;
2736    case SANE_FRAME_RED:
2737      text_format = "red";
2738      break;
2739    case SANE_FRAME_GREEN:
2740      text_format = "green";
2741      break;
2742    case SANE_FRAME_BLUE:
2743      text_format = "blue";
2744      break;
2745    default:
2746      text_format = "unknown";
2747      break;
2748    }
2749
2750  DBG (3, "sane_get_parameters: format=%s\n", text_format);
2751  DBG (3, "sane_get_parameters: last_frame=%s\n",
2752       p->last_frame ? "true" : "false");
2753  DBG (3, "sane_get_parameters: lines=%d\n", p->lines);
2754  DBG (3, "sane_get_parameters: depth=%d\n", p->depth);
2755  DBG (3, "sane_get_parameters: pixels_per_line=%d\n", p->pixels_per_line);
2756  DBG (3, "sane_get_parameters: bytes_per_line=%d\n", p->bytes_per_line);
2757
2758  if (params)
2759    *params = *p;
2760
2761  return SANE_STATUS_GOOD;
2762}
2763
2764SANE_Status
2765sane_start (SANE_Handle handle)
2766{
2767  Test_Device *test_device = handle;
2768  int pipe_descriptor[2];
2769
2770  DBG (2, "sane_start: handle=%p\n", handle);
2771  if (!inited)
2772    {
2773      DBG (1, "sane_start: not inited, call sane_init() first\n");
2774      return SANE_STATUS_INVAL;
2775    }
2776  if (!check_handle (handle))
2777    {
2778      DBG (1, "sane_start: handle %p unknown\n", handle);
2779      return SANE_STATUS_INVAL;
2780    }
2781  if (!test_device->open)
2782    {
2783      DBG (1, "sane_start: not open\n");
2784      return SANE_STATUS_INVAL;
2785    }
2786  if (test_device->scanning
2787      && (test_device->val[opt_three_pass].w == SANE_FALSE
2788	  && strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0))
2789    {
2790      DBG (1, "sane_start: already scanning\n");
2791      return SANE_STATUS_INVAL;
2792    }
2793  if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0
2794      && test_device->val[opt_three_pass].w == SANE_TRUE
2795      && test_device->pass > 2)
2796    {
2797      DBG (1, "sane_start: already in last pass of three\n");
2798      return SANE_STATUS_INVAL;
2799    }
2800
2801  if (test_device->pass == 0)
2802    {
2803      test_device->number_of_scans++;
2804      DBG (3, "sane_start: scanning page %d\n", test_device->number_of_scans);
2805
2806      if ((strcmp (test_device->val[opt_scan_source].s, "Automatic Document Feeder") == 0) &&
2807	  (((test_device->number_of_scans) % 11) == 0))
2808	{
2809	  DBG (1, "sane_start: Document feeder is out of documents!\n");
2810	  return SANE_STATUS_NO_DOCS;
2811	}
2812    }
2813
2814  test_device->scanning = SANE_TRUE;
2815  test_device->cancelled = SANE_FALSE;
2816  test_device->eof = SANE_FALSE;
2817  test_device->bytes_total = 0;
2818
2819  sane_get_parameters (handle, 0);
2820
2821  if (test_device->params.lines == 0)
2822    {
2823      DBG (1, "sane_start: lines == 0\n");
2824      test_device->scanning = SANE_FALSE;
2825      return SANE_STATUS_INVAL;
2826    }
2827  if (test_device->params.pixels_per_line == 0)
2828    {
2829      DBG (1, "sane_start: pixels_per_line == 0\n");
2830      test_device->scanning = SANE_FALSE;
2831      return SANE_STATUS_INVAL;
2832    }
2833  if (test_device->params.bytes_per_line == 0)
2834    {
2835      DBG (1, "sane_start: bytes_per_line == 0\n");
2836      test_device->scanning = SANE_FALSE;
2837      return SANE_STATUS_INVAL;
2838    }
2839
2840  if (pipe (pipe_descriptor) < 0)
2841    {
2842      DBG (1, "sane_start: pipe failed (%s)\n", strerror (errno));
2843      return SANE_STATUS_IO_ERROR;
2844    }
2845
2846  /* create reader routine as new process or thread */
2847  test_device->pipe = pipe_descriptor[0];
2848  test_device->reader_fds = pipe_descriptor[1];
2849  test_device->reader_pid =
2850    sanei_thread_begin (reader_task, (void *) test_device);
2851
2852  if (!sanei_thread_is_valid (test_device->reader_pid))
2853    {
2854      DBG (1, "sane_start: sanei_thread_begin failed (%s)\n",
2855	   strerror (errno));
2856      return SANE_STATUS_NO_MEM;
2857    }
2858
2859  if (sanei_thread_is_forked ())
2860    {
2861      close (test_device->reader_fds);
2862      test_device->reader_fds = -1;
2863    }
2864
2865  return SANE_STATUS_GOOD;
2866}
2867
2868
2869SANE_Status
2870sane_read (SANE_Handle handle, SANE_Byte * data,
2871	   SANE_Int max_length, SANE_Int * length)
2872{
2873  Test_Device *test_device = handle;
2874  SANE_Int max_scan_length;
2875  ssize_t bytes_read;
2876  size_t read_count;
2877  size_t bytes_total = (size_t) test_device->lines * (size_t) test_device->bytes_per_line;
2878
2879
2880  DBG (4, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n",
2881       handle, (void *) data, max_length, (void *) length);
2882  if (!inited)
2883    {
2884      DBG (1, "sane_read: not inited, call sane_init() first\n");
2885      return SANE_STATUS_INVAL;
2886    }
2887  if (!check_handle (handle))
2888    {
2889      DBG (1, "sane_read: handle %p unknown\n", handle);
2890      return SANE_STATUS_INVAL;
2891    }
2892  if (!length)
2893    {
2894      DBG (1, "sane_read: length == NULL\n");
2895      return SANE_STATUS_INVAL;
2896    }
2897
2898  if (strcmp (test_device->val[opt_read_status_code].s, "Default") != 0)
2899    {
2900      SANE_String_Const sc = test_device->val[opt_read_status_code].s;
2901      DBG (3, "sane_read: setting return status to %s\n", sc);
2902      if (strcmp (sc, "SANE_STATUS_UNSUPPORTED") == 0)
2903	return SANE_STATUS_UNSUPPORTED;
2904      if (strcmp (sc, "SANE_STATUS_CANCELLED") == 0)
2905	return SANE_STATUS_CANCELLED;
2906      if (strcmp (sc, "SANE_STATUS_DEVICE_BUSY") == 0)
2907	return SANE_STATUS_DEVICE_BUSY;
2908      if (strcmp (sc, "SANE_STATUS_INVAL") == 0)
2909	return SANE_STATUS_INVAL;
2910      if (strcmp (sc, "SANE_STATUS_EOF") == 0)
2911	return SANE_STATUS_EOF;
2912      if (strcmp (sc, "SANE_STATUS_JAMMED") == 0)
2913	return SANE_STATUS_JAMMED;
2914      if (strcmp (sc, "SANE_STATUS_NO_DOCS") == 0)
2915	return SANE_STATUS_NO_DOCS;
2916      if (strcmp (sc, "SANE_STATUS_COVER_OPEN") == 0)
2917	return SANE_STATUS_COVER_OPEN;
2918      if (strcmp (sc, "SANE_STATUS_IO_ERROR") == 0)
2919	return SANE_STATUS_IO_ERROR;
2920      if (strcmp (sc, "SANE_STATUS_NO_MEM") == 0)
2921	return SANE_STATUS_NO_MEM;
2922      if (strcmp (sc, "SANE_STATUS_ACCESS_DENIED") == 0)
2923	return SANE_STATUS_ACCESS_DENIED;
2924    }
2925
2926  max_scan_length = max_length;
2927  if (test_device->val[opt_read_limit].w == SANE_TRUE
2928      && test_device->val[opt_read_limit_size].w < max_scan_length)
2929    {
2930      max_scan_length = test_device->val[opt_read_limit_size].w;
2931      DBG (3, "sane_read: limiting max_scan_length to %d bytes\n",
2932	   max_scan_length);
2933    }
2934
2935  *length = 0;
2936
2937  if (!data)
2938    {
2939      DBG (1, "sane_read: data == NULL\n");
2940      return SANE_STATUS_INVAL;
2941    }
2942  if (!test_device->open)
2943    {
2944      DBG (1, "sane_read: not open\n");
2945      return SANE_STATUS_INVAL;
2946    }
2947  if (test_device->cancelled)
2948    {
2949      DBG (1, "sane_read: scan was cancelled\n");
2950      return SANE_STATUS_CANCELLED;
2951    }
2952  if (test_device->eof)
2953    {
2954      DBG (2, "sane_read: No more data available, sending EOF\n");
2955      return SANE_STATUS_EOF;
2956    }
2957  if (!test_device->scanning)
2958    {
2959      DBG (1, "sane_read: not scanning (call sane_start first)\n");
2960      return SANE_STATUS_INVAL;
2961    }
2962  read_count = (size_t) max_scan_length;
2963
2964  bytes_read = read (test_device->pipe, data, read_count);
2965  if (bytes_read == 0
2966      || ((size_t) bytes_read + (size_t) test_device->bytes_total >= bytes_total))
2967    {
2968      SANE_Status status;
2969      DBG (2, "sane_read: EOF reached\n");
2970      status = finish_pass (test_device);
2971      if (status != SANE_STATUS_GOOD)
2972	{
2973	  DBG (1, "sane_read: finish_pass returned `%s'\n",
2974	       sane_strstatus (status));
2975	  return status;
2976	}
2977      test_device->eof = SANE_TRUE;
2978      if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0
2979	  && test_device->val[opt_three_pass].w == SANE_TRUE)
2980	{
2981	  test_device->pass++;
2982	  if (test_device->pass > 2)
2983	    test_device->pass = 0;
2984	}
2985      if (bytes_read == 0)
2986	return SANE_STATUS_EOF;
2987    }
2988  else if (bytes_read < 0)
2989    {
2990      if (errno == EAGAIN)
2991	{
2992	  DBG (2, "sane_read: no data available, try again\n");
2993	  return SANE_STATUS_GOOD;
2994	}
2995      else
2996	{
2997	  DBG (1, "sane_read: read returned error: %s\n", strerror (errno));
2998	  return SANE_STATUS_IO_ERROR;
2999	}
3000    }
3001  *length = (SANE_Int) bytes_read;
3002  test_device->bytes_total += (size_t) bytes_read;
3003
3004  DBG (2, "sane_read: read %zu bytes of %zu, total %zu\n", (size_t) bytes_read,
3005       (size_t) max_scan_length, (size_t) test_device->bytes_total);
3006  return SANE_STATUS_GOOD;
3007}
3008
3009void
3010sane_cancel (SANE_Handle handle)
3011{
3012  Test_Device *test_device = handle;
3013
3014  DBG (2, "sane_cancel: handle = %p\n", handle);
3015  if (!inited)
3016    {
3017      DBG (1, "sane_cancel: not inited, call sane_init() first\n");
3018      return;
3019    }
3020  if (!check_handle (handle))
3021    {
3022      DBG (1, "sane_cancel: handle %p unknown\n", handle);
3023      return;
3024    }
3025  if (!test_device->open)
3026    {
3027      DBG (1, "sane_cancel: not open\n");
3028      return;
3029    }
3030  if (test_device->cancelled)
3031    {
3032      DBG (1, "sane_cancel: scan already cancelled\n");
3033      return;
3034    }
3035  if (!test_device->scanning)
3036    {
3037      DBG (2, "sane_cancel: scan is already finished\n");
3038      return;
3039    }
3040  finish_pass (test_device);
3041  test_device->cancelled = SANE_TRUE;
3042  test_device->scanning = SANE_FALSE;
3043  test_device->eof = SANE_FALSE;
3044  test_device->pass = 0;
3045  return;
3046}
3047
3048SANE_Status
3049sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
3050{
3051  Test_Device *test_device = handle;
3052
3053  DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
3054       non_blocking);
3055  if (!inited)
3056    {
3057      DBG (1, "sane_set_io_mode: not inited, call sane_init() first\n");
3058      return SANE_STATUS_INVAL;
3059    }
3060  if (!check_handle (handle))
3061    {
3062      DBG (1, "sane_set_io_mode: handle %p unknown\n", handle);
3063      return SANE_STATUS_INVAL;
3064    }
3065  if (!test_device->open)
3066    {
3067      DBG (1, "sane_set_io_mode: not open\n");
3068      return SANE_STATUS_INVAL;
3069    }
3070  if (!test_device->scanning)
3071    {
3072      DBG (1, "sane_set_io_mode: not scanning\n");
3073      return SANE_STATUS_INVAL;
3074    }
3075  if (test_device->val[opt_non_blocking].w == SANE_TRUE)
3076    {
3077      if (fcntl (test_device->pipe,
3078		 F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
3079	{
3080	  DBG (1, "sane_set_io_mode: can't set io mode");
3081	  return SANE_STATUS_INVAL;
3082	}
3083    }
3084  else
3085    {
3086      DBG (1, "sane_set_io_mode: unsupported\n");
3087      if (non_blocking)
3088	return SANE_STATUS_UNSUPPORTED;
3089    }
3090  return SANE_STATUS_GOOD;
3091}
3092
3093SANE_Status
3094sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
3095{
3096  Test_Device *test_device = handle;
3097
3098  DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
3099       fd ? "!=" : "=");
3100  if (!inited)
3101    {
3102      DBG (1, "sane_get_select_fd: not inited, call sane_init() first\n");
3103      return SANE_STATUS_INVAL;
3104    }
3105  if (!check_handle (handle))
3106    {
3107      DBG (1, "sane_get_select_fd: handle %p unknown\n", handle);
3108      return SANE_STATUS_INVAL;
3109    }
3110  if (!test_device->open)
3111    {
3112      DBG (1, "sane_get_select_fd: not open\n");
3113      return SANE_STATUS_INVAL;
3114    }
3115  if (!test_device->scanning)
3116    {
3117      DBG (1, "sane_get_select_fd: not scanning\n");
3118      return SANE_STATUS_INVAL;
3119    }
3120  if (test_device->val[opt_select_fd].w == SANE_TRUE)
3121    {
3122      *fd = test_device->pipe;
3123      return SANE_STATUS_GOOD;
3124    }
3125  DBG(1,"sane_get_select_fd: unsupported\n");
3126  return SANE_STATUS_UNSUPPORTED;
3127}
3128