1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 2002-2006 Henning Meier-Geinitz <henning@meier-geinitz.de>
4141cc406Sopenharmony_ci   Changes according to the sanei_thread usage by
5141cc406Sopenharmony_ci                                         Gerhard Jaeger <gerhard@gjaeger.de>
6141cc406Sopenharmony_ci
7141cc406Sopenharmony_ci   This file is part of the SANE package.
8141cc406Sopenharmony_ci
9141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
10141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
11141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
12141cc406Sopenharmony_ci   License, or (at your option) any later version.
13141cc406Sopenharmony_ci
14141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
15141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
16141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17141cc406Sopenharmony_ci   General Public License for more details.
18141cc406Sopenharmony_ci
19141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
20141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
21141cc406Sopenharmony_ci
22141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
23141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
24141cc406Sopenharmony_ci
25141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
26141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
27141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
28141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
29141cc406Sopenharmony_ci   account of linking the SANE library code into it.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
32141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
33141cc406Sopenharmony_ci   License.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
36141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
37141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
40141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
41141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
42141cc406Sopenharmony_ci
43141cc406Sopenharmony_ci   This backend is for testing frontends.
44141cc406Sopenharmony_ci*/
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#define BUILD 28
47141cc406Sopenharmony_ci
48141cc406Sopenharmony_ci#include "../include/sane/config.h"
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include <errno.h>
51141cc406Sopenharmony_ci#include <signal.h>
52141cc406Sopenharmony_ci#include <stdio.h>
53141cc406Sopenharmony_ci#include <stdlib.h>
54141cc406Sopenharmony_ci#include <string.h>
55141cc406Sopenharmony_ci#include <sys/types.h>
56141cc406Sopenharmony_ci#include <time.h>
57141cc406Sopenharmony_ci#include <unistd.h>
58141cc406Sopenharmony_ci#include <fcntl.h>
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#include "../include/_stdint.h"
61141cc406Sopenharmony_ci
62141cc406Sopenharmony_ci#include "../include/sane/sane.h"
63141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
64141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
65141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
66141cc406Sopenharmony_ci#include "../include/sane/sanei_thread.h"
67141cc406Sopenharmony_ci
68141cc406Sopenharmony_ci#define BACKEND_NAME	test
69141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
70141cc406Sopenharmony_ci
71141cc406Sopenharmony_ci#include "test.h"
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_ci#include "test-picture.c"
74141cc406Sopenharmony_ci
75141cc406Sopenharmony_ci#define TEST_CONFIG_FILE "test.conf"
76141cc406Sopenharmony_ci
77141cc406Sopenharmony_cistatic SANE_Bool inited = SANE_FALSE;
78141cc406Sopenharmony_cistatic SANE_Device **sane_device_list = 0;
79141cc406Sopenharmony_cistatic Test_Device *first_test_device = 0;
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_cistatic SANE_Range geometry_range = {
82141cc406Sopenharmony_ci  SANE_FIX (0.0),
83141cc406Sopenharmony_ci  SANE_FIX (200.0),
84141cc406Sopenharmony_ci  SANE_FIX (1.0)
85141cc406Sopenharmony_ci};
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_cistatic SANE_Range resolution_range = {
88141cc406Sopenharmony_ci  SANE_FIX (1.0),
89141cc406Sopenharmony_ci  SANE_FIX (1200.0),
90141cc406Sopenharmony_ci  SANE_FIX (1.0)
91141cc406Sopenharmony_ci};
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_cistatic SANE_Range ppl_loss_range = {
94141cc406Sopenharmony_ci  0,
95141cc406Sopenharmony_ci  128,
96141cc406Sopenharmony_ci  1
97141cc406Sopenharmony_ci};
98141cc406Sopenharmony_ci
99141cc406Sopenharmony_cistatic SANE_Range read_limit_size_range = {
100141cc406Sopenharmony_ci  1,
101141cc406Sopenharmony_ci  64 * 1024,			/* 64 KB ought to be enough for everyone :-) */
102141cc406Sopenharmony_ci  1
103141cc406Sopenharmony_ci};
104141cc406Sopenharmony_ci
105141cc406Sopenharmony_cistatic SANE_Range read_delay_duration_range = {
106141cc406Sopenharmony_ci  1000,
107141cc406Sopenharmony_ci  200 * 1000,			/* 200 msec */
108141cc406Sopenharmony_ci  1000
109141cc406Sopenharmony_ci};
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_cistatic SANE_Range int_constraint_range = {
112141cc406Sopenharmony_ci  4,
113141cc406Sopenharmony_ci  192,
114141cc406Sopenharmony_ci  2
115141cc406Sopenharmony_ci};
116141cc406Sopenharmony_ci
117141cc406Sopenharmony_cistatic SANE_Range gamma_range = {
118141cc406Sopenharmony_ci  0,
119141cc406Sopenharmony_ci  255,
120141cc406Sopenharmony_ci  1
121141cc406Sopenharmony_ci};
122141cc406Sopenharmony_ci
123141cc406Sopenharmony_cistatic SANE_Range fixed_constraint_range = {
124141cc406Sopenharmony_ci  SANE_FIX (-42.17),
125141cc406Sopenharmony_ci  SANE_FIX (32767.9999),
126141cc406Sopenharmony_ci  SANE_FIX (2.0)
127141cc406Sopenharmony_ci};
128141cc406Sopenharmony_ci
129141cc406Sopenharmony_cistatic SANE_String_Const mode_list[] = {
130141cc406Sopenharmony_ci  SANE_VALUE_SCAN_MODE_GRAY,
131141cc406Sopenharmony_ci  SANE_VALUE_SCAN_MODE_COLOR,
132141cc406Sopenharmony_ci  0
133141cc406Sopenharmony_ci};
134141cc406Sopenharmony_ci
135141cc406Sopenharmony_cistatic SANE_String_Const order_list[] = {
136141cc406Sopenharmony_ci  "RGB", "RBG", "GBR", "GRB", "BRG", "BGR",
137141cc406Sopenharmony_ci  0
138141cc406Sopenharmony_ci};
139141cc406Sopenharmony_ci
140141cc406Sopenharmony_cistatic SANE_String_Const test_picture_list[] = {
141141cc406Sopenharmony_ci  SANE_I18N ("Solid black"), SANE_I18N ("Solid white"),
142141cc406Sopenharmony_ci  SANE_I18N ("Color pattern"), SANE_I18N ("Grid"),
143141cc406Sopenharmony_ci  0
144141cc406Sopenharmony_ci};
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_cistatic SANE_String_Const read_status_code_list[] = {
147141cc406Sopenharmony_ci  SANE_I18N ("Default"), "SANE_STATUS_UNSUPPORTED", "SANE_STATUS_CANCELLED",
148141cc406Sopenharmony_ci  "SANE_STATUS_DEVICE_BUSY", "SANE_STATUS_INVAL", "SANE_STATUS_EOF",
149141cc406Sopenharmony_ci  "SANE_STATUS_JAMMED", "SANE_STATUS_NO_DOCS", "SANE_STATUS_COVER_OPEN",
150141cc406Sopenharmony_ci  "SANE_STATUS_IO_ERROR", "SANE_STATUS_NO_MEM", "SANE_STATUS_ACCESS_DENIED",
151141cc406Sopenharmony_ci  0
152141cc406Sopenharmony_ci};
153141cc406Sopenharmony_ci
154141cc406Sopenharmony_cistatic SANE_Int depth_list[] = {
155141cc406Sopenharmony_ci  3, 1, 8, 16
156141cc406Sopenharmony_ci};
157141cc406Sopenharmony_ci
158141cc406Sopenharmony_cistatic SANE_Int int_constraint_word_list[] = {
159141cc406Sopenharmony_ci  9, -42, -8, 0, 17, 42, 256, 65536, 256 * 256 * 256, 256 * 256 * 256 * 64
160141cc406Sopenharmony_ci};
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_cistatic SANE_Int fixed_constraint_word_list[] = {
163141cc406Sopenharmony_ci  4, SANE_FIX (-32.7), SANE_FIX (12.1), SANE_FIX (42.0), SANE_FIX (129.5)
164141cc406Sopenharmony_ci};
165141cc406Sopenharmony_ci
166141cc406Sopenharmony_cistatic SANE_String_Const string_constraint_string_list[] = {
167141cc406Sopenharmony_ci  SANE_I18N ("First entry"), SANE_I18N ("Second entry"),
168141cc406Sopenharmony_ci  SANE_I18N
169141cc406Sopenharmony_ci    ("This is the very long third entry. Maybe the frontend has an idea how to "
170141cc406Sopenharmony_ci     "display it"),
171141cc406Sopenharmony_ci  0
172141cc406Sopenharmony_ci};
173141cc406Sopenharmony_ci
174141cc406Sopenharmony_cistatic SANE_String_Const string_constraint_long_string_list[] = {
175141cc406Sopenharmony_ci  SANE_I18N ("First entry"), SANE_I18N ("Second entry"), "3", "4", "5", "6",
176141cc406Sopenharmony_ci  "7", "8", "9", "10",
177141cc406Sopenharmony_ci  "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",
178141cc406Sopenharmony_ci  "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34",
179141cc406Sopenharmony_ci  "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46",
180141cc406Sopenharmony_ci  0
181141cc406Sopenharmony_ci};
182141cc406Sopenharmony_ci
183141cc406Sopenharmony_cistatic SANE_Int int_array[] = {
184141cc406Sopenharmony_ci  -17, 0, -5, 42, 91, 256 * 256 * 256 * 64
185141cc406Sopenharmony_ci};
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_cistatic SANE_Int int_array_constraint_range[] = {
188141cc406Sopenharmony_ci  48, 6, 4, 92, 190, 16
189141cc406Sopenharmony_ci};
190141cc406Sopenharmony_ci
191141cc406Sopenharmony_ci#define GAMMA_RED_SIZE 256
192141cc406Sopenharmony_ci#define GAMMA_GREEN_SIZE 256
193141cc406Sopenharmony_ci#define GAMMA_BLUE_SIZE 256
194141cc406Sopenharmony_ci#define GAMMA_ALL_SIZE 4096
195141cc406Sopenharmony_cistatic SANE_Int gamma_red[GAMMA_RED_SIZE]; // initialized in init_options()
196141cc406Sopenharmony_cistatic SANE_Int gamma_green[GAMMA_GREEN_SIZE];
197141cc406Sopenharmony_cistatic SANE_Int gamma_blue[GAMMA_BLUE_SIZE];
198141cc406Sopenharmony_cistatic SANE_Int gamma_all[GAMMA_ALL_SIZE];
199141cc406Sopenharmony_ci
200141cc406Sopenharmony_cistatic void
201141cc406Sopenharmony_ciinit_gamma_table(SANE_Int *tablePtr, SANE_Int count, SANE_Int max)
202141cc406Sopenharmony_ci{
203141cc406Sopenharmony_ci  for (int i=0; i<count; ++i) {
204141cc406Sopenharmony_ci    tablePtr[i] = (SANE_Int)(((double)i * max)/(double)count);
205141cc406Sopenharmony_ci  }
206141cc406Sopenharmony_ci}
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_cistatic void
209141cc406Sopenharmony_ciprint_gamma_table(SANE_Int *tablePtr, SANE_Int count)
210141cc406Sopenharmony_ci{
211141cc406Sopenharmony_ci  char str[200];
212141cc406Sopenharmony_ci  str[0] = '\0';
213141cc406Sopenharmony_ci  DBG (5, "Gamma Table Size: %d\n", count);
214141cc406Sopenharmony_ci  for (int i=0; i<count; ++i) {
215141cc406Sopenharmony_ci    if (i%16 == 0 && strlen(str) > 0) {
216141cc406Sopenharmony_ci      DBG (5, "%s\n", str);
217141cc406Sopenharmony_ci      str[0] = '\0';
218141cc406Sopenharmony_ci    }
219141cc406Sopenharmony_ci    sprintf (str + strlen(str), " %04X", tablePtr[i]);
220141cc406Sopenharmony_ci  }
221141cc406Sopenharmony_ci  if (strlen(str) > 0) {
222141cc406Sopenharmony_ci    DBG (5, "%s\n", str);
223141cc406Sopenharmony_ci  }
224141cc406Sopenharmony_ci}
225141cc406Sopenharmony_ci
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_cistatic SANE_Int int_array_constraint_word_list[] = {
228141cc406Sopenharmony_ci  -42, 0, -8, 17, 42, 42
229141cc406Sopenharmony_ci};
230141cc406Sopenharmony_ci
231141cc406Sopenharmony_cistatic SANE_String_Const source_list[] = {
232141cc406Sopenharmony_ci  SANE_I18N ("Flatbed"), SANE_I18N ("Automatic Document Feeder"),
233141cc406Sopenharmony_ci  0
234141cc406Sopenharmony_ci};
235141cc406Sopenharmony_ci
236141cc406Sopenharmony_cistatic double random_factor;	/* use for fuzzyness of parameters */
237141cc406Sopenharmony_ci
238141cc406Sopenharmony_ci/* initial values. Initial string values are set in sane_init() */
239141cc406Sopenharmony_cistatic SANE_Word init_number_of_devices = 2;
240141cc406Sopenharmony_cistatic SANE_Fixed init_tl_x = SANE_FIX (0.0);
241141cc406Sopenharmony_cistatic SANE_Fixed init_tl_y = SANE_FIX (0.0);
242141cc406Sopenharmony_cistatic SANE_Fixed init_br_x = SANE_FIX (80.0);
243141cc406Sopenharmony_cistatic SANE_Fixed init_br_y = SANE_FIX (100.0);
244141cc406Sopenharmony_cistatic SANE_Word init_resolution = 50;
245141cc406Sopenharmony_cistatic SANE_String init_mode = NULL;
246141cc406Sopenharmony_cistatic SANE_Word init_depth = 8;
247141cc406Sopenharmony_cistatic SANE_Bool init_hand_scanner = SANE_FALSE;
248141cc406Sopenharmony_cistatic SANE_Bool init_three_pass = SANE_FALSE;
249141cc406Sopenharmony_cistatic SANE_String init_three_pass_order = NULL;
250141cc406Sopenharmony_cistatic SANE_String init_scan_source = NULL;
251141cc406Sopenharmony_cistatic SANE_String init_test_picture = NULL;
252141cc406Sopenharmony_cistatic SANE_Bool init_invert_endianess = SANE_FALSE;
253141cc406Sopenharmony_cistatic SANE_Bool init_read_limit = SANE_FALSE;
254141cc406Sopenharmony_cistatic SANE_Word init_read_limit_size = 1;
255141cc406Sopenharmony_cistatic SANE_Bool init_read_delay = SANE_FALSE;
256141cc406Sopenharmony_cistatic SANE_Word init_read_delay_duration = 1000;
257141cc406Sopenharmony_cistatic SANE_String init_read_status_code = NULL;
258141cc406Sopenharmony_cistatic SANE_Bool init_fuzzy_parameters = SANE_FALSE;
259141cc406Sopenharmony_cistatic SANE_Word init_ppl_loss = 0;
260141cc406Sopenharmony_cistatic SANE_Bool init_non_blocking = SANE_FALSE;
261141cc406Sopenharmony_cistatic SANE_Bool init_select_fd = SANE_FALSE;
262141cc406Sopenharmony_cistatic SANE_Bool init_enable_test_options = SANE_FALSE;
263141cc406Sopenharmony_cistatic SANE_String init_string = NULL;
264141cc406Sopenharmony_cistatic SANE_String init_string_constraint_string_list = NULL;
265141cc406Sopenharmony_cistatic SANE_String init_string_constraint_long_string_list = NULL;
266141cc406Sopenharmony_ci
267141cc406Sopenharmony_ci/* Test if this machine is little endian (from coolscan.c) */
268141cc406Sopenharmony_cistatic SANE_Bool
269141cc406Sopenharmony_cilittle_endian (void)
270141cc406Sopenharmony_ci{
271141cc406Sopenharmony_ci  SANE_Int testvalue = 255;
272141cc406Sopenharmony_ci  uint8_t *firstbyte = (uint8_t *) & testvalue;
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_ci  if (*firstbyte == 255)
275141cc406Sopenharmony_ci    return SANE_TRUE;
276141cc406Sopenharmony_ci  return SANE_FALSE;
277141cc406Sopenharmony_ci}
278141cc406Sopenharmony_ci
279141cc406Sopenharmony_cistatic void
280141cc406Sopenharmony_ciswap_double (double *a, double *b)
281141cc406Sopenharmony_ci{
282141cc406Sopenharmony_ci  double c;
283141cc406Sopenharmony_ci
284141cc406Sopenharmony_ci  c = *a;
285141cc406Sopenharmony_ci  *a = *b;
286141cc406Sopenharmony_ci  *b = c;
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_ci  return;
289141cc406Sopenharmony_ci}
290141cc406Sopenharmony_ci
291141cc406Sopenharmony_cistatic size_t
292141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
293141cc406Sopenharmony_ci{
294141cc406Sopenharmony_ci  size_t size, max_size = 0;
295141cc406Sopenharmony_ci  SANE_Int i;
296141cc406Sopenharmony_ci
297141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
298141cc406Sopenharmony_ci    {
299141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
300141cc406Sopenharmony_ci      if (size > max_size)
301141cc406Sopenharmony_ci	max_size = size;
302141cc406Sopenharmony_ci    }
303141cc406Sopenharmony_ci  return max_size;
304141cc406Sopenharmony_ci}
305141cc406Sopenharmony_ci
306141cc406Sopenharmony_cistatic SANE_Bool
307141cc406Sopenharmony_cicheck_handle (SANE_Handle handle)
308141cc406Sopenharmony_ci{
309141cc406Sopenharmony_ci  Test_Device *test_device = first_test_device;
310141cc406Sopenharmony_ci
311141cc406Sopenharmony_ci  while (test_device)
312141cc406Sopenharmony_ci    {
313141cc406Sopenharmony_ci      if (test_device == (Test_Device *) handle)
314141cc406Sopenharmony_ci	return SANE_TRUE;
315141cc406Sopenharmony_ci      test_device = test_device->next;
316141cc406Sopenharmony_ci    }
317141cc406Sopenharmony_ci  return SANE_FALSE;
318141cc406Sopenharmony_ci}
319141cc406Sopenharmony_ci
320141cc406Sopenharmony_cistatic void
321141cc406Sopenharmony_cicleanup_options (Test_Device * test_device)
322141cc406Sopenharmony_ci{
323141cc406Sopenharmony_ci  DBG (2, "cleanup_options: test_device=%p\n", (void *) test_device);
324141cc406Sopenharmony_ci
325141cc406Sopenharmony_ci  free(test_device->val[opt_mode].s);
326141cc406Sopenharmony_ci  test_device->val[opt_mode].s = NULL;
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci  free(test_device->val[opt_three_pass_order].s);
329141cc406Sopenharmony_ci  test_device->val[opt_three_pass_order].s = NULL;
330141cc406Sopenharmony_ci
331141cc406Sopenharmony_ci  free(test_device->val[opt_scan_source].s);
332141cc406Sopenharmony_ci  test_device->val[opt_scan_source].s = NULL;
333141cc406Sopenharmony_ci
334141cc406Sopenharmony_ci  free(test_device->val[opt_test_picture].s);
335141cc406Sopenharmony_ci  test_device->val[opt_test_picture].s = NULL;
336141cc406Sopenharmony_ci
337141cc406Sopenharmony_ci  free(test_device->val[opt_read_status_code].s);
338141cc406Sopenharmony_ci  test_device->val[opt_read_status_code].s = NULL;
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci  free(test_device->val[opt_string].s);
341141cc406Sopenharmony_ci  test_device->val[opt_string].s = NULL;
342141cc406Sopenharmony_ci
343141cc406Sopenharmony_ci  free(test_device->val[opt_string_constraint_string_list].s);
344141cc406Sopenharmony_ci  test_device->val[opt_string_constraint_string_list].s = NULL;
345141cc406Sopenharmony_ci
346141cc406Sopenharmony_ci  free(test_device->val[opt_string_constraint_long_string_list].s);
347141cc406Sopenharmony_ci  test_device->val[opt_string_constraint_long_string_list].s = NULL;
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_ci  test_device->options_initialized = SANE_FALSE;
350141cc406Sopenharmony_ci}
351141cc406Sopenharmony_ci
352141cc406Sopenharmony_cistatic SANE_Status
353141cc406Sopenharmony_ciinit_options (Test_Device * test_device)
354141cc406Sopenharmony_ci{
355141cc406Sopenharmony_ci  SANE_Option_Descriptor *od;
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_ci  DBG (2, "init_options: test_device=%p\n", (void *) test_device);
358141cc406Sopenharmony_ci
359141cc406Sopenharmony_ci  /* opt_num_opts */
360141cc406Sopenharmony_ci  od = &test_device->opt[opt_num_opts];
361141cc406Sopenharmony_ci  od->name = "";
362141cc406Sopenharmony_ci  od->title = SANE_TITLE_NUM_OPTIONS;
363141cc406Sopenharmony_ci  od->desc = SANE_DESC_NUM_OPTIONS;
364141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
365141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
366141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
367141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT;
368141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
369141cc406Sopenharmony_ci  od->constraint.range = 0;
370141cc406Sopenharmony_ci  test_device->val[opt_num_opts].w = num_options;
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci  test_device->loaded[opt_num_opts] = 1;
373141cc406Sopenharmony_ci
374141cc406Sopenharmony_ci  /* opt_mode_group */
375141cc406Sopenharmony_ci  od = &test_device->opt[opt_mode_group];
376141cc406Sopenharmony_ci  od->name = "";
377141cc406Sopenharmony_ci  od->title = SANE_I18N ("Scan Mode");
378141cc406Sopenharmony_ci  od->desc = "";
379141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
380141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
381141cc406Sopenharmony_ci  od->size = 0;
382141cc406Sopenharmony_ci  od->cap = 0;
383141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
384141cc406Sopenharmony_ci  od->constraint.range = 0;
385141cc406Sopenharmony_ci  test_device->val[opt_mode_group].w = 0;
386141cc406Sopenharmony_ci
387141cc406Sopenharmony_ci  /* opt_mode */
388141cc406Sopenharmony_ci  od = &test_device->opt[opt_mode];
389141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_MODE;
390141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_MODE;
391141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_MODE;
392141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
393141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
394141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (mode_list);
395141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
396141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
397141cc406Sopenharmony_ci  od->constraint.string_list = mode_list;
398141cc406Sopenharmony_ci  test_device->val[opt_mode].s = malloc ((size_t) od->size);
399141cc406Sopenharmony_ci  if (!test_device->val[opt_mode].s)
400141cc406Sopenharmony_ci    goto fail;
401141cc406Sopenharmony_ci  strcpy (test_device->val[opt_mode].s, init_mode);
402141cc406Sopenharmony_ci
403141cc406Sopenharmony_ci  /* opt_depth */
404141cc406Sopenharmony_ci  od = &test_device->opt[opt_depth];
405141cc406Sopenharmony_ci  od->name = SANE_NAME_BIT_DEPTH;
406141cc406Sopenharmony_ci  od->title = SANE_TITLE_BIT_DEPTH;
407141cc406Sopenharmony_ci  od->desc = SANE_DESC_BIT_DEPTH;
408141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
409141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
410141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
411141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
412141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
413141cc406Sopenharmony_ci  od->constraint.word_list = depth_list;
414141cc406Sopenharmony_ci  test_device->val[opt_depth].w = init_depth;
415141cc406Sopenharmony_ci
416141cc406Sopenharmony_ci  /* opt_hand_scanner */
417141cc406Sopenharmony_ci  od = &test_device->opt[opt_hand_scanner];
418141cc406Sopenharmony_ci  od->name = "hand-scanner";
419141cc406Sopenharmony_ci  od->title = SANE_I18N ("Hand-scanner simulation");
420141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Simulate a hand-scanner.  Hand-scanners do not "
421141cc406Sopenharmony_ci			"know the image height a priori.  Instead, they "
422141cc406Sopenharmony_ci			"return a height of -1.  Setting this option allows one "
423141cc406Sopenharmony_ci			"to test whether a frontend can handle this "
424141cc406Sopenharmony_ci			"correctly.  This option also enables a fixed width "
425141cc406Sopenharmony_ci			"of 11 cm.");
426141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
427141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
428141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
429141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
430141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
431141cc406Sopenharmony_ci  od->constraint.range = 0;
432141cc406Sopenharmony_ci  test_device->val[opt_hand_scanner].w = init_hand_scanner;
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_ci  /* opt_three_pass */
435141cc406Sopenharmony_ci  od = &test_device->opt[opt_three_pass];
436141cc406Sopenharmony_ci  od->name = "three-pass";
437141cc406Sopenharmony_ci  od->title = SANE_I18N ("Three-pass simulation");
438141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Simulate a three-pass scanner. In color mode, three "
439141cc406Sopenharmony_ci			"frames are transmitted.");
440141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
441141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
442141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
443141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
444141cc406Sopenharmony_ci  if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0)
445141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
446141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
447141cc406Sopenharmony_ci  od->constraint.range = 0;
448141cc406Sopenharmony_ci  test_device->val[opt_three_pass].w = init_three_pass;
449141cc406Sopenharmony_ci
450141cc406Sopenharmony_ci  /* opt_three_pass_order */
451141cc406Sopenharmony_ci  od = &test_device->opt[opt_three_pass_order];
452141cc406Sopenharmony_ci  od->name = "three-pass-order";
453141cc406Sopenharmony_ci  od->title = SANE_I18N ("Set the order of frames");
454141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Set the order of frames in three-pass color mode.");
455141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
456141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
457141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (order_list);
458141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
459141cc406Sopenharmony_ci  if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0)
460141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
461141cc406Sopenharmony_ci  if (!init_three_pass)
462141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
463141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
464141cc406Sopenharmony_ci  od->constraint.string_list = order_list;
465141cc406Sopenharmony_ci  test_device->val[opt_three_pass_order].s = malloc ((size_t) od->size);
466141cc406Sopenharmony_ci  if (!test_device->val[opt_three_pass_order].s)
467141cc406Sopenharmony_ci    goto fail;
468141cc406Sopenharmony_ci  strcpy (test_device->val[opt_three_pass_order].s, init_three_pass_order);
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci  /* opt_resolution */
471141cc406Sopenharmony_ci  od = &test_device->opt[opt_resolution];
472141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_RESOLUTION;
473141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_RESOLUTION;
474141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_RESOLUTION;
475141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
476141cc406Sopenharmony_ci  od->unit = SANE_UNIT_DPI;
477141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
478141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
479141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
480141cc406Sopenharmony_ci  od->constraint.range = &resolution_range;
481141cc406Sopenharmony_ci  test_device->val[opt_resolution].w = init_resolution;
482141cc406Sopenharmony_ci
483141cc406Sopenharmony_ci  /* opt_scan_source */
484141cc406Sopenharmony_ci  od = &test_device->opt[opt_scan_source];
485141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_SOURCE;
486141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_SOURCE;
487141cc406Sopenharmony_ci  od->desc = SANE_I18N("If Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.");
488141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
489141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
490141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (source_list);
491141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
492141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
493141cc406Sopenharmony_ci  od->constraint.string_list = source_list;
494141cc406Sopenharmony_ci  test_device->val[opt_scan_source].s = malloc ((size_t) od->size);
495141cc406Sopenharmony_ci  if (!test_device->val[opt_scan_source].s)
496141cc406Sopenharmony_ci    goto fail;
497141cc406Sopenharmony_ci  strcpy (test_device->val[opt_scan_source].s, init_scan_source);
498141cc406Sopenharmony_ci
499141cc406Sopenharmony_ci  /* opt_special_group */
500141cc406Sopenharmony_ci  od = &test_device->opt[opt_special_group];
501141cc406Sopenharmony_ci  od->name = "";
502141cc406Sopenharmony_ci  od->title = SANE_I18N ("Special Options");
503141cc406Sopenharmony_ci  od->desc = "";
504141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
505141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
506141cc406Sopenharmony_ci  od->size = 0;
507141cc406Sopenharmony_ci  od->cap = 0;
508141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
509141cc406Sopenharmony_ci  od->constraint.range = 0;
510141cc406Sopenharmony_ci  test_device->val[opt_special_group].w = 0;
511141cc406Sopenharmony_ci
512141cc406Sopenharmony_ci  /* opt_test_picture */
513141cc406Sopenharmony_ci  od = &test_device->opt[opt_test_picture];
514141cc406Sopenharmony_ci  od->name = "test-picture";
515141cc406Sopenharmony_ci  od->title = SANE_I18N ("Select the test picture");
516141cc406Sopenharmony_ci  od->desc =
517141cc406Sopenharmony_ci    SANE_I18N ("Select the kind of test picture. Available options:\n"
518141cc406Sopenharmony_ci	       "Solid black: fills the whole scan with black.\n"
519141cc406Sopenharmony_ci	       "Solid white: fills the whole scan with white.\n"
520141cc406Sopenharmony_ci	       "Color pattern: draws various color test patterns "
521141cc406Sopenharmony_ci	       "depending on the mode.\n"
522141cc406Sopenharmony_ci	       "Grid: draws a black/white grid with a width and "
523141cc406Sopenharmony_ci	       "height of 10 mm per square.");
524141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
525141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
526141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (test_picture_list);
527141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
528141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
529141cc406Sopenharmony_ci  od->constraint.string_list = test_picture_list;
530141cc406Sopenharmony_ci  test_device->val[opt_test_picture].s = malloc ((size_t) od->size);
531141cc406Sopenharmony_ci  if (!test_device->val[opt_test_picture].s)
532141cc406Sopenharmony_ci    goto fail;
533141cc406Sopenharmony_ci  strcpy (test_device->val[opt_test_picture].s, init_test_picture);
534141cc406Sopenharmony_ci
535141cc406Sopenharmony_ci  /* opt_invert_endianness */
536141cc406Sopenharmony_ci  od = &test_device->opt[opt_invert_endianess];
537141cc406Sopenharmony_ci  od->name = "invert-endianess";
538141cc406Sopenharmony_ci  od->title = SANE_I18N ("Invert endianness");
539141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Exchange upper and lower byte of image data in 16 "
540141cc406Sopenharmony_ci			"bit modes. This option can be used to test the 16 "
541141cc406Sopenharmony_ci			"bit modes of frontends, e.g. if the frontend uses "
542141cc406Sopenharmony_ci			"the correct endianness.");
543141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
544141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
545141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
546141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
547141cc406Sopenharmony_ci  od->cap |= SANE_CAP_INACTIVE;
548141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
549141cc406Sopenharmony_ci  od->constraint.range = 0;
550141cc406Sopenharmony_ci  test_device->val[opt_invert_endianess].w = init_invert_endianess;
551141cc406Sopenharmony_ci
552141cc406Sopenharmony_ci  /* opt_read_limit */
553141cc406Sopenharmony_ci  od = &test_device->opt[opt_read_limit];
554141cc406Sopenharmony_ci  od->name = "read-limit";
555141cc406Sopenharmony_ci  od->title = SANE_I18N ("Read limit");
556141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Limit the amount of data transferred with each "
557141cc406Sopenharmony_ci			"call to sane_read().");
558141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
559141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
560141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
561141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
562141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
563141cc406Sopenharmony_ci  od->constraint.range = 0;
564141cc406Sopenharmony_ci  test_device->val[opt_read_limit].w = init_read_limit;
565141cc406Sopenharmony_ci
566141cc406Sopenharmony_ci  /* opt_read_limit_size */
567141cc406Sopenharmony_ci  od = &test_device->opt[opt_read_limit_size];
568141cc406Sopenharmony_ci  od->name = "read-limit-size";
569141cc406Sopenharmony_ci  od->title = SANE_I18N ("Size of read-limit");
570141cc406Sopenharmony_ci  od->desc = SANE_I18N ("The (maximum) amount of data transferred with each "
571141cc406Sopenharmony_ci			"call to sane_read().");
572141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
573141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
574141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
575141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
576141cc406Sopenharmony_ci  if (!init_read_limit)
577141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
578141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
579141cc406Sopenharmony_ci  od->constraint.range = &read_limit_size_range;
580141cc406Sopenharmony_ci  test_device->val[opt_read_limit_size].w = init_read_limit_size;
581141cc406Sopenharmony_ci
582141cc406Sopenharmony_ci  /* opt_read_delay */
583141cc406Sopenharmony_ci  od = &test_device->opt[opt_read_delay];
584141cc406Sopenharmony_ci  od->name = "read-delay";
585141cc406Sopenharmony_ci  od->title = SANE_I18N ("Read delay");
586141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Delay the transfer of data to the pipe.");
587141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
588141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
589141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
590141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
591141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
592141cc406Sopenharmony_ci  od->constraint.range = 0;
593141cc406Sopenharmony_ci  test_device->val[opt_read_delay].w = init_read_delay;
594141cc406Sopenharmony_ci
595141cc406Sopenharmony_ci  /* opt_read_delay_duration */
596141cc406Sopenharmony_ci  od = &test_device->opt[opt_read_delay_duration];
597141cc406Sopenharmony_ci  od->name = "read-delay-duration";
598141cc406Sopenharmony_ci  od->title = SANE_I18N ("Duration of read-delay");
599141cc406Sopenharmony_ci  od->desc = SANE_I18N ("How long to wait after transferring each buffer of "
600141cc406Sopenharmony_ci			"data through the pipe.");
601141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
602141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MICROSECOND;
603141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
604141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
605141cc406Sopenharmony_ci  if (!init_read_delay)
606141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
607141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
608141cc406Sopenharmony_ci  od->constraint.range = &read_delay_duration_range;
609141cc406Sopenharmony_ci  test_device->val[opt_read_delay_duration].w = init_read_delay_duration;
610141cc406Sopenharmony_ci
611141cc406Sopenharmony_ci  /* opt_read_status_code */
612141cc406Sopenharmony_ci  od = &test_device->opt[opt_read_status_code];
613141cc406Sopenharmony_ci  od->name = "read-return-value";
614141cc406Sopenharmony_ci  od->title = SANE_I18N ("Return-value of sane_read");
615141cc406Sopenharmony_ci  od->desc =
616141cc406Sopenharmony_ci    SANE_I18N ("Select the return-value of sane_read(). \"Default\" "
617141cc406Sopenharmony_ci	       "is the normal handling for scanning. All other status "
618141cc406Sopenharmony_ci	       "codes are for testing how the frontend handles them.");
619141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
620141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
621141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (read_status_code_list);
622141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
623141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
624141cc406Sopenharmony_ci  od->constraint.string_list = read_status_code_list;
625141cc406Sopenharmony_ci  test_device->val[opt_read_status_code].s = malloc ((size_t) od->size);
626141cc406Sopenharmony_ci  if (!test_device->val[opt_read_status_code].s)
627141cc406Sopenharmony_ci    goto fail;
628141cc406Sopenharmony_ci  strcpy (test_device->val[opt_read_status_code].s, init_read_status_code);
629141cc406Sopenharmony_ci
630141cc406Sopenharmony_ci  /* opt_ppl_loss */
631141cc406Sopenharmony_ci  od = &test_device->opt[opt_ppl_loss];
632141cc406Sopenharmony_ci  od->name = "ppl-loss";
633141cc406Sopenharmony_ci  od->title = SANE_I18N ("Loss of pixels per line");
634141cc406Sopenharmony_ci  od->desc =
635141cc406Sopenharmony_ci    SANE_I18N ("The number of pixels that are wasted at the end of each "
636141cc406Sopenharmony_ci	       "line.");
637141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
638141cc406Sopenharmony_ci  od->unit = SANE_UNIT_PIXEL;
639141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
640141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
641141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
642141cc406Sopenharmony_ci  od->constraint.range = &ppl_loss_range;
643141cc406Sopenharmony_ci  test_device->val[opt_ppl_loss].w = init_ppl_loss;
644141cc406Sopenharmony_ci
645141cc406Sopenharmony_ci  /* opt_fuzzy_parameters */
646141cc406Sopenharmony_ci  od = &test_device->opt[opt_fuzzy_parameters];
647141cc406Sopenharmony_ci  od->name = "fuzzy-parameters";
648141cc406Sopenharmony_ci  od->title = SANE_I18N ("Fuzzy parameters");
649141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Return fuzzy lines and bytes per line when "
650141cc406Sopenharmony_ci			"sane_parameters() is called before sane_start().");
651141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
652141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
653141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
654141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
655141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
656141cc406Sopenharmony_ci  od->constraint.range = 0;
657141cc406Sopenharmony_ci  test_device->val[opt_fuzzy_parameters].w = init_fuzzy_parameters;
658141cc406Sopenharmony_ci
659141cc406Sopenharmony_ci  /* opt_non_blocking */
660141cc406Sopenharmony_ci  od = &test_device->opt[opt_non_blocking];
661141cc406Sopenharmony_ci  od->name = "non-blocking";
662141cc406Sopenharmony_ci  od->title = SANE_I18N ("Use non-blocking IO");
663141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported "
664141cc406Sopenharmony_ci			"by the frontend.");
665141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
666141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
667141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
668141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
669141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
670141cc406Sopenharmony_ci  od->constraint.range = 0;
671141cc406Sopenharmony_ci  test_device->val[opt_non_blocking].w = init_non_blocking;
672141cc406Sopenharmony_ci
673141cc406Sopenharmony_ci  /* opt_select_fd */
674141cc406Sopenharmony_ci  od = &test_device->opt[opt_select_fd];
675141cc406Sopenharmony_ci  od->name = "select-fd";
676141cc406Sopenharmony_ci  od->title = SANE_I18N ("Offer select file descriptor");
677141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Offer a select filedescriptor for detecting if "
678141cc406Sopenharmony_ci			"sane_read() will return data.");
679141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
680141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
681141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
682141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
683141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
684141cc406Sopenharmony_ci  od->constraint.range = 0;
685141cc406Sopenharmony_ci  test_device->val[opt_select_fd].w = init_select_fd;
686141cc406Sopenharmony_ci
687141cc406Sopenharmony_ci  /* opt_enable_test_options */
688141cc406Sopenharmony_ci  od = &test_device->opt[opt_enable_test_options];
689141cc406Sopenharmony_ci  od->name = "enable-test-options";
690141cc406Sopenharmony_ci  od->title = SANE_I18N ("Enable test options");
691141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Enable various test options. This is for testing "
692141cc406Sopenharmony_ci			"the ability of frontends to view and modify all the "
693141cc406Sopenharmony_ci			"different SANE option types.");
694141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
695141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
696141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
697141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
698141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
699141cc406Sopenharmony_ci  od->constraint.range = 0;
700141cc406Sopenharmony_ci  test_device->val[opt_enable_test_options].w = init_enable_test_options;
701141cc406Sopenharmony_ci
702141cc406Sopenharmony_ci  /* opt_print_options */
703141cc406Sopenharmony_ci  od = &test_device->opt[opt_print_options];
704141cc406Sopenharmony_ci  od->name = "print-options";
705141cc406Sopenharmony_ci  od->title = SANE_I18N ("Print options");
706141cc406Sopenharmony_ci  od->desc = SANE_I18N ("Print a list of all options.");
707141cc406Sopenharmony_ci  od->type = SANE_TYPE_BUTTON;
708141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
709141cc406Sopenharmony_ci  od->size = 0;
710141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
711141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
712141cc406Sopenharmony_ci  od->constraint.string_list = 0;
713141cc406Sopenharmony_ci  test_device->val[opt_print_options].w = 0;
714141cc406Sopenharmony_ci
715141cc406Sopenharmony_ci  /* opt_geometry_group */
716141cc406Sopenharmony_ci  od = &test_device->opt[opt_geometry_group];
717141cc406Sopenharmony_ci  od->name = "";
718141cc406Sopenharmony_ci  od->title = SANE_I18N ("Geometry");
719141cc406Sopenharmony_ci  od->desc = "";
720141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
721141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
722141cc406Sopenharmony_ci  od->size = 0;
723141cc406Sopenharmony_ci  od->cap = 0;
724141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
725141cc406Sopenharmony_ci  od->constraint.range = 0;
726141cc406Sopenharmony_ci  test_device->val[opt_geometry_group].w = 0;
727141cc406Sopenharmony_ci
728141cc406Sopenharmony_ci  /* opt_tl_x */
729141cc406Sopenharmony_ci  od = &test_device->opt[opt_tl_x];
730141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_TL_X;
731141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_TL_X;
732141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_TL_X;
733141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
734141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MM;
735141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
736141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
737141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
738141cc406Sopenharmony_ci  od->constraint.range = &geometry_range;
739141cc406Sopenharmony_ci  test_device->val[opt_tl_x].w = init_tl_x;
740141cc406Sopenharmony_ci
741141cc406Sopenharmony_ci  /* opt_tl_y */
742141cc406Sopenharmony_ci  od = &test_device->opt[opt_tl_y];
743141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_TL_Y;
744141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_TL_Y;
745141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_TL_Y;
746141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
747141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MM;
748141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
749141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
750141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
751141cc406Sopenharmony_ci  od->constraint.range = &geometry_range;
752141cc406Sopenharmony_ci  test_device->val[opt_tl_y].w = init_tl_y;
753141cc406Sopenharmony_ci
754141cc406Sopenharmony_ci  /* opt_br_x */
755141cc406Sopenharmony_ci  od = &test_device->opt[opt_br_x];
756141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_BR_X;
757141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_BR_X;
758141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_BR_X;
759141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
760141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MM;
761141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
762141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
763141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
764141cc406Sopenharmony_ci  od->constraint.range = &geometry_range;
765141cc406Sopenharmony_ci  test_device->val[opt_br_x].w = init_br_x;
766141cc406Sopenharmony_ci
767141cc406Sopenharmony_ci  /* opt_br_y */
768141cc406Sopenharmony_ci  od = &test_device->opt[opt_br_y];
769141cc406Sopenharmony_ci  od->name = SANE_NAME_SCAN_BR_Y;
770141cc406Sopenharmony_ci  od->title = SANE_TITLE_SCAN_BR_Y;
771141cc406Sopenharmony_ci  od->desc = SANE_DESC_SCAN_BR_Y;
772141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
773141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MM;
774141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
775141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
776141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
777141cc406Sopenharmony_ci  od->constraint.range = &geometry_range;
778141cc406Sopenharmony_ci  test_device->val[opt_br_y].w = init_br_y;
779141cc406Sopenharmony_ci
780141cc406Sopenharmony_ci  /* opt_bool_group */
781141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_group];
782141cc406Sopenharmony_ci  od->name = "";
783141cc406Sopenharmony_ci  od->title = SANE_I18N ("Bool test options");
784141cc406Sopenharmony_ci  od->desc = "";
785141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
786141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
787141cc406Sopenharmony_ci  od->size = 0;
788141cc406Sopenharmony_ci  od->cap = SANE_CAP_ADVANCED;
789141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
790141cc406Sopenharmony_ci  od->constraint.range = 0;
791141cc406Sopenharmony_ci  test_device->val[opt_bool_group].w = 0;
792141cc406Sopenharmony_ci
793141cc406Sopenharmony_ci  /* opt_bool_soft_select_soft_detect */
794141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_soft_select_soft_detect];
795141cc406Sopenharmony_ci  od->name = "bool-soft-select-soft-detect";
796141cc406Sopenharmony_ci  od->title = SANE_I18N ("(1/6) Bool soft select soft detect");
797141cc406Sopenharmony_ci  od->desc =
798141cc406Sopenharmony_ci    SANE_I18N ("(1/6) Bool test option that has soft select and soft "
799141cc406Sopenharmony_ci	       "detect (and advanced) capabilities. That's just a "
800141cc406Sopenharmony_ci	       "normal bool option.");
801141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
802141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
803141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
804141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
805141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
806141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
807141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
808141cc406Sopenharmony_ci  od->constraint.range = 0;
809141cc406Sopenharmony_ci  test_device->val[opt_bool_soft_select_soft_detect].w = SANE_FALSE;
810141cc406Sopenharmony_ci
811141cc406Sopenharmony_ci  /* opt_bool_hard_select_soft_detect */
812141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_hard_select_soft_detect];
813141cc406Sopenharmony_ci  od->name = "bool-hard-select-soft-detect";
814141cc406Sopenharmony_ci  od->title = SANE_I18N ("(2/6) Bool hard select soft detect");
815141cc406Sopenharmony_ci  od->desc =
816141cc406Sopenharmony_ci    SANE_I18N ("(2/6) Bool test option that has hard select and soft "
817141cc406Sopenharmony_ci	       "detect (and advanced) capabilities. That means the "
818141cc406Sopenharmony_ci	       "option can't be set by the frontend but by the user "
819141cc406Sopenharmony_ci	       "(e.g. by pressing a button at the device).");
820141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
821141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
822141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
823141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
824141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
825141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
826141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
827141cc406Sopenharmony_ci  od->constraint.range = 0;
828141cc406Sopenharmony_ci  test_device->val[opt_bool_hard_select_soft_detect].w = SANE_FALSE;
829141cc406Sopenharmony_ci
830141cc406Sopenharmony_ci  /* opt_bool_hard_select */
831141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_hard_select];
832141cc406Sopenharmony_ci  od->name = "bool-hard-select";
833141cc406Sopenharmony_ci  od->title = SANE_I18N ("(3/6) Bool hard select");
834141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(3/6) Bool test option that has hard select "
835141cc406Sopenharmony_ci			"(and advanced) capabilities. That means the option "
836141cc406Sopenharmony_ci			"can't be set by the frontend but by the user "
837141cc406Sopenharmony_ci			"(e.g. by pressing a button at the device) and can't "
838141cc406Sopenharmony_ci			"be read by the frontend.");
839141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
840141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
841141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
842141cc406Sopenharmony_ci  od->cap = SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
843141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
844141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
845141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
846141cc406Sopenharmony_ci  od->constraint.range = 0;
847141cc406Sopenharmony_ci  test_device->val[opt_bool_hard_select].w = SANE_FALSE;
848141cc406Sopenharmony_ci
849141cc406Sopenharmony_ci  /* opt_bool_soft_detect */
850141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_soft_detect];
851141cc406Sopenharmony_ci  od->name = "bool-soft-detect";
852141cc406Sopenharmony_ci  od->title = SANE_I18N ("(4/6) Bool soft detect");
853141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(4/6) Bool test option that has soft detect "
854141cc406Sopenharmony_ci			"(and advanced) capabilities. That means the option "
855141cc406Sopenharmony_ci			"is read-only.");
856141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
857141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
858141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
859141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
860141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
861141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
862141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
863141cc406Sopenharmony_ci  od->constraint.range = 0;
864141cc406Sopenharmony_ci  test_device->val[opt_bool_soft_detect].w = SANE_FALSE;
865141cc406Sopenharmony_ci
866141cc406Sopenharmony_ci  /* opt_bool_soft_select_soft_detect_emulated */
867141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_soft_select_soft_detect_emulated];
868141cc406Sopenharmony_ci  od->name = "bool-soft-select-soft-detect-emulated";
869141cc406Sopenharmony_ci  od->title = SANE_I18N ("(5/6) Bool soft select soft detect emulated");
870141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(5/6) Bool test option that has soft select, soft "
871141cc406Sopenharmony_ci			"detect, and emulated (and advanced) capabilities.");
872141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
873141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
874141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
875141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED
876141cc406Sopenharmony_ci    | SANE_CAP_EMULATED;
877141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
878141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
879141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
880141cc406Sopenharmony_ci  od->constraint.range = 0;
881141cc406Sopenharmony_ci  test_device->val[opt_bool_soft_select_soft_detect_emulated].w = SANE_FALSE;
882141cc406Sopenharmony_ci
883141cc406Sopenharmony_ci  /* opt_bool_soft_select_soft_detect_auto */
884141cc406Sopenharmony_ci  od = &test_device->opt[opt_bool_soft_select_soft_detect_auto];
885141cc406Sopenharmony_ci  od->name = "bool-soft-select-soft-detect-auto";
886141cc406Sopenharmony_ci  od->title = SANE_I18N ("(6/6) Bool soft select soft detect auto");
887141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(6/6) Bool test option that has soft select, soft "
888141cc406Sopenharmony_ci			"detect, and automatic (and advanced) capabilities. "
889141cc406Sopenharmony_ci			"This option can be automatically set by the backend.");
890141cc406Sopenharmony_ci  od->type = SANE_TYPE_BOOL;
891141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
892141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
893141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED
894141cc406Sopenharmony_ci    | SANE_CAP_AUTOMATIC;
895141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
896141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
897141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
898141cc406Sopenharmony_ci  od->constraint.range = 0;
899141cc406Sopenharmony_ci  test_device->val[opt_bool_soft_select_soft_detect_auto].w = SANE_FALSE;
900141cc406Sopenharmony_ci
901141cc406Sopenharmony_ci  /* opt_int_group */
902141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_group];
903141cc406Sopenharmony_ci  od->name = "";
904141cc406Sopenharmony_ci  od->title = SANE_I18N ("Int test options");
905141cc406Sopenharmony_ci  od->desc = "";
906141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
907141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
908141cc406Sopenharmony_ci  od->size = 0;
909141cc406Sopenharmony_ci  od->cap = SANE_CAP_ADVANCED;
910141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
911141cc406Sopenharmony_ci  od->constraint.range = 0;
912141cc406Sopenharmony_ci  test_device->val[opt_int_group].w = 0;
913141cc406Sopenharmony_ci
914141cc406Sopenharmony_ci  /* opt_int */
915141cc406Sopenharmony_ci  od = &test_device->opt[opt_int];
916141cc406Sopenharmony_ci  od->name = "int";
917141cc406Sopenharmony_ci  od->title = SANE_I18N ("(1/7) Int");
918141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(1/7) Int test option with no unit and no "
919141cc406Sopenharmony_ci			"constraint set.");
920141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
921141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
922141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
923141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
924141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
925141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
926141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
927141cc406Sopenharmony_ci  od->constraint.range = 0;
928141cc406Sopenharmony_ci  test_device->val[opt_int].w = 42;
929141cc406Sopenharmony_ci
930141cc406Sopenharmony_ci  /* opt_int_constraint_range */
931141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_constraint_range];
932141cc406Sopenharmony_ci  od->name = "int-constraint-range";
933141cc406Sopenharmony_ci  od->title = SANE_I18N ("(2/7) Int constraint range");
934141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(2/7) Int test option with unit pixel and "
935141cc406Sopenharmony_ci			"constraint range set. Minimum is 4, maximum 192, and "
936141cc406Sopenharmony_ci			"quant is 2.");
937141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
938141cc406Sopenharmony_ci  od->unit = SANE_UNIT_PIXEL;
939141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
940141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
941141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
942141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
943141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
944141cc406Sopenharmony_ci  od->constraint.range = &int_constraint_range;
945141cc406Sopenharmony_ci  test_device->val[opt_int_constraint_range].w = 26;
946141cc406Sopenharmony_ci
947141cc406Sopenharmony_ci  /* opt_int_constraint_word_list */
948141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_constraint_word_list];
949141cc406Sopenharmony_ci  od->name = "int-constraint-word-list";
950141cc406Sopenharmony_ci  od->title = SANE_I18N ("(3/7) Int constraint word list");
951141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(3/7) Int test option with unit bits and "
952141cc406Sopenharmony_ci			"constraint word list set.");
953141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
954141cc406Sopenharmony_ci  od->unit = SANE_UNIT_BIT;
955141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
956141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
957141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
958141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
959141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
960141cc406Sopenharmony_ci  od->constraint.word_list = int_constraint_word_list;
961141cc406Sopenharmony_ci  test_device->val[opt_int_constraint_word_list].w = 42;
962141cc406Sopenharmony_ci
963141cc406Sopenharmony_ci  /* opt_int_array */
964141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_array];
965141cc406Sopenharmony_ci  od->name = "int-constraint-array";
966141cc406Sopenharmony_ci  od->title = SANE_I18N ("(4/7) Int array");
967141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(4/7) Int test option with unit mm and using "
968141cc406Sopenharmony_ci			"an array without constraints.");
969141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
970141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MM;
971141cc406Sopenharmony_ci  od->size = 6 * sizeof (SANE_Word);
972141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
973141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
974141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
975141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
976141cc406Sopenharmony_ci  od->constraint.range = 0;
977141cc406Sopenharmony_ci  test_device->val[opt_int_array].wa = &int_array[0];
978141cc406Sopenharmony_ci
979141cc406Sopenharmony_ci  /* opt_int_array_constraint_range */
980141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_array_constraint_range];
981141cc406Sopenharmony_ci  od->name = "int-constraint-array-constraint-range";
982141cc406Sopenharmony_ci  od->title = SANE_I18N ("(5/7) Int array constraint range");
983141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(5/7) Int test option with unit dpi and using "
984141cc406Sopenharmony_ci			"an array with a range constraint. Minimum is 4, "
985141cc406Sopenharmony_ci			"maximum 192, and quant is 2.");
986141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
987141cc406Sopenharmony_ci  od->unit = SANE_UNIT_DPI;
988141cc406Sopenharmony_ci  od->size = 6 * sizeof (SANE_Word);
989141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
990141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
991141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
992141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
993141cc406Sopenharmony_ci  od->constraint.range = &int_constraint_range;
994141cc406Sopenharmony_ci  test_device->val[opt_int_array_constraint_range].wa =
995141cc406Sopenharmony_ci    &int_array_constraint_range[0];
996141cc406Sopenharmony_ci
997141cc406Sopenharmony_ci /* opt_int_array_constraint_word_list */
998141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_array_constraint_word_list];
999141cc406Sopenharmony_ci  od->name = "int-constraint-array-constraint-word-list";
1000141cc406Sopenharmony_ci  od->title = SANE_I18N ("(6/7) Int array constraint word list");
1001141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(6/7) Int test option with unit percent and using "
1002141cc406Sopenharmony_ci			"an array with a word list constraint.");
1003141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1004141cc406Sopenharmony_ci  od->unit = SANE_UNIT_PERCENT;
1005141cc406Sopenharmony_ci  od->size = 6 * sizeof (SANE_Word);
1006141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1007141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1008141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1009141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1010141cc406Sopenharmony_ci  od->constraint.word_list = int_constraint_word_list;
1011141cc406Sopenharmony_ci  test_device->val[opt_int_array_constraint_word_list].wa =
1012141cc406Sopenharmony_ci    &int_array_constraint_word_list[0];
1013141cc406Sopenharmony_ci
1014141cc406Sopenharmony_ci  /* opt_int_inexact */
1015141cc406Sopenharmony_ci  od = &test_device->opt[opt_int_inexact];
1016141cc406Sopenharmony_ci  od->name = "int-inexact";
1017141cc406Sopenharmony_ci  od->title = SANE_I18N ("(7/7) Int inexact");
1018141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(7/7) Int test option that modifies the value "
1019141cc406Sopenharmony_ci			"and returns SANE_INFO_INEXACT.");
1020141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1021141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1022141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
1023141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1024141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1025141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1026141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1027141cc406Sopenharmony_ci  od->constraint.range = 0;
1028141cc406Sopenharmony_ci  test_device->val[opt_int_inexact].w = 67;
1029141cc406Sopenharmony_ci
1030141cc406Sopenharmony_ci
1031141cc406Sopenharmony_ci  /* opt_gamma_red */
1032141cc406Sopenharmony_ci  init_gamma_table(gamma_red, GAMMA_RED_SIZE, gamma_range.max);
1033141cc406Sopenharmony_ci  od = &test_device->opt[opt_gamma_red];
1034141cc406Sopenharmony_ci  od->name = SANE_NAME_GAMMA_VECTOR_R;
1035141cc406Sopenharmony_ci  od->title = SANE_TITLE_GAMMA_VECTOR_R;
1036141cc406Sopenharmony_ci  od->desc = SANE_DESC_GAMMA_VECTOR_R;
1037141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1038141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1039141cc406Sopenharmony_ci  od->size = 256 * sizeof (SANE_Word);
1040141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1041141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
1042141cc406Sopenharmony_ci  od->constraint.range = &gamma_range;
1043141cc406Sopenharmony_ci  test_device->val[opt_gamma_red].wa = &gamma_red[0];
1044141cc406Sopenharmony_ci
1045141cc406Sopenharmony_ci  /* opt_gamma_green */
1046141cc406Sopenharmony_ci  init_gamma_table(gamma_green, GAMMA_GREEN_SIZE, gamma_range.max);
1047141cc406Sopenharmony_ci  od = &test_device->opt[opt_gamma_green];
1048141cc406Sopenharmony_ci  od->name = SANE_NAME_GAMMA_VECTOR_G;
1049141cc406Sopenharmony_ci  od->title = SANE_TITLE_GAMMA_VECTOR_G;
1050141cc406Sopenharmony_ci  od->desc = SANE_DESC_GAMMA_VECTOR_G;
1051141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1052141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1053141cc406Sopenharmony_ci  od->size = 256 * sizeof (SANE_Word);
1054141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1055141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
1056141cc406Sopenharmony_ci  od->constraint.range = &gamma_range;
1057141cc406Sopenharmony_ci  test_device->val[opt_gamma_green].wa = &gamma_green[0];
1058141cc406Sopenharmony_ci
1059141cc406Sopenharmony_ci  /* opt_gamma_blue */
1060141cc406Sopenharmony_ci  init_gamma_table(gamma_blue, GAMMA_BLUE_SIZE, gamma_range.max);
1061141cc406Sopenharmony_ci  od = &test_device->opt[opt_gamma_blue];
1062141cc406Sopenharmony_ci  od->name = SANE_NAME_GAMMA_VECTOR_B;
1063141cc406Sopenharmony_ci  od->title = SANE_TITLE_GAMMA_VECTOR_B;
1064141cc406Sopenharmony_ci  od->desc = SANE_DESC_GAMMA_VECTOR_B;
1065141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1066141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1067141cc406Sopenharmony_ci  od->size = 256 * sizeof (SANE_Word);
1068141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1069141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
1070141cc406Sopenharmony_ci  od->constraint.range = &gamma_range;
1071141cc406Sopenharmony_ci  test_device->val[opt_gamma_blue].wa = &gamma_blue[0];
1072141cc406Sopenharmony_ci
1073141cc406Sopenharmony_ci  /* opt_gamma_all */
1074141cc406Sopenharmony_ci  init_gamma_table(gamma_all, GAMMA_ALL_SIZE, gamma_range.max);
1075141cc406Sopenharmony_ci  print_gamma_table(gamma_all, GAMMA_ALL_SIZE);
1076141cc406Sopenharmony_ci  od = &test_device->opt[opt_gamma_all];
1077141cc406Sopenharmony_ci  od->name = SANE_NAME_GAMMA_VECTOR;
1078141cc406Sopenharmony_ci  od->title = SANE_TITLE_GAMMA_VECTOR;
1079141cc406Sopenharmony_ci  od->desc = SANE_DESC_GAMMA_VECTOR;
1080141cc406Sopenharmony_ci  od->type = SANE_TYPE_INT;
1081141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1082141cc406Sopenharmony_ci  od->size = GAMMA_ALL_SIZE * sizeof (SANE_Word);
1083141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1084141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
1085141cc406Sopenharmony_ci  od->constraint.range = &gamma_range;
1086141cc406Sopenharmony_ci  test_device->val[opt_gamma_all].wa = &gamma_all[0];
1087141cc406Sopenharmony_ci
1088141cc406Sopenharmony_ci  /* opt_fixed_group */
1089141cc406Sopenharmony_ci  od = &test_device->opt[opt_fixed_group];
1090141cc406Sopenharmony_ci  od->name = "";
1091141cc406Sopenharmony_ci  od->title = SANE_I18N ("Fixed test options");
1092141cc406Sopenharmony_ci  od->desc = "";
1093141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
1094141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1095141cc406Sopenharmony_ci  od->size = 0;
1096141cc406Sopenharmony_ci  od->cap = SANE_CAP_ADVANCED;
1097141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1098141cc406Sopenharmony_ci  od->constraint.range = 0;
1099141cc406Sopenharmony_ci  test_device->val[opt_fixed_group].w = 0;
1100141cc406Sopenharmony_ci
1101141cc406Sopenharmony_ci  /* opt_fixed */
1102141cc406Sopenharmony_ci  od = &test_device->opt[opt_fixed];
1103141cc406Sopenharmony_ci  od->name = "fixed";
1104141cc406Sopenharmony_ci  od->title = SANE_I18N ("(1/3) Fixed");
1105141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(1/3) Fixed test option with no unit and no "
1106141cc406Sopenharmony_ci			"constraint set.");
1107141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
1108141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1109141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
1110141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1111141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1112141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1113141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1114141cc406Sopenharmony_ci  od->constraint.range = 0;
1115141cc406Sopenharmony_ci  test_device->val[opt_fixed].w = SANE_FIX (42.0);
1116141cc406Sopenharmony_ci
1117141cc406Sopenharmony_ci  /* opt_fixed_constraint_range */
1118141cc406Sopenharmony_ci  od = &test_device->opt[opt_fixed_constraint_range];
1119141cc406Sopenharmony_ci  od->name = "fixed-constraint-range";
1120141cc406Sopenharmony_ci  od->title = SANE_I18N ("(2/3) Fixed constraint range");
1121141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(2/3) Fixed test option with unit microsecond and "
1122141cc406Sopenharmony_ci			"constraint range set. Minimum is -42.17, maximum "
1123141cc406Sopenharmony_ci			"32767.9999, and quant is 2.0.");
1124141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
1125141cc406Sopenharmony_ci  od->unit = SANE_UNIT_MICROSECOND;
1126141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
1127141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1128141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1129141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1130141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_RANGE;
1131141cc406Sopenharmony_ci  od->constraint.range = &fixed_constraint_range;
1132141cc406Sopenharmony_ci  test_device->val[opt_fixed_constraint_range].w = SANE_FIX (41.83);
1133141cc406Sopenharmony_ci
1134141cc406Sopenharmony_ci  /* opt_fixed_constraint_word_list */
1135141cc406Sopenharmony_ci  od = &test_device->opt[opt_fixed_constraint_word_list];
1136141cc406Sopenharmony_ci  od->name = "fixed-constraint-word-list";
1137141cc406Sopenharmony_ci  od->title = SANE_I18N ("(3/3) Fixed constraint word list");
1138141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(3/3) Fixed test option with no unit and "
1139141cc406Sopenharmony_ci			"constraint word list set.");
1140141cc406Sopenharmony_ci  od->type = SANE_TYPE_FIXED;
1141141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1142141cc406Sopenharmony_ci  od->size = sizeof (SANE_Word);
1143141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED;
1144141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1145141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1146141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_WORD_LIST;
1147141cc406Sopenharmony_ci  od->constraint.word_list = fixed_constraint_word_list;
1148141cc406Sopenharmony_ci  test_device->val[opt_fixed_constraint_word_list].w = SANE_FIX (42.0);
1149141cc406Sopenharmony_ci
1150141cc406Sopenharmony_ci  /* opt_string_group */
1151141cc406Sopenharmony_ci  od = &test_device->opt[opt_string_group];
1152141cc406Sopenharmony_ci  od->name = "";
1153141cc406Sopenharmony_ci  od->title = SANE_I18N ("String test options");
1154141cc406Sopenharmony_ci  od->desc = "";
1155141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
1156141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1157141cc406Sopenharmony_ci  od->size = 0;
1158141cc406Sopenharmony_ci  od->cap = 0;
1159141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1160141cc406Sopenharmony_ci  od->constraint.range = 0;
1161141cc406Sopenharmony_ci  test_device->val[opt_string_group].w = 0;
1162141cc406Sopenharmony_ci
1163141cc406Sopenharmony_ci  /* opt_string */
1164141cc406Sopenharmony_ci  od = &test_device->opt[opt_string];
1165141cc406Sopenharmony_ci  od->name = "string";
1166141cc406Sopenharmony_ci  od->title = SANE_I18N ("(1/3) String");
1167141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(1/3) String test option without constraint.");
1168141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
1169141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1170141cc406Sopenharmony_ci  od->size = (SANE_Int) strlen (init_string) + 1;
1171141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1172141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1173141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1174141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1175141cc406Sopenharmony_ci  od->constraint.string_list = 0;
1176141cc406Sopenharmony_ci  test_device->val[opt_string].s = malloc ((size_t) od->size);
1177141cc406Sopenharmony_ci  if (!test_device->val[opt_string].s)
1178141cc406Sopenharmony_ci    goto fail;
1179141cc406Sopenharmony_ci  strcpy (test_device->val[opt_string].s, init_string);
1180141cc406Sopenharmony_ci
1181141cc406Sopenharmony_ci  /* opt_string_constraint_string_list */
1182141cc406Sopenharmony_ci  od = &test_device->opt[opt_string_constraint_string_list];
1183141cc406Sopenharmony_ci  od->name = "string-constraint-string-list";
1184141cc406Sopenharmony_ci  od->title = SANE_I18N ("(2/3) String constraint string list");
1185141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(2/3) String test option with string list "
1186141cc406Sopenharmony_ci			"constraint.");
1187141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
1188141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1189141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (string_constraint_string_list);
1190141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1191141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1192141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1193141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1194141cc406Sopenharmony_ci  od->constraint.string_list = string_constraint_string_list;
1195141cc406Sopenharmony_ci  test_device->val[opt_string_constraint_string_list].s = malloc ((size_t) od->size);
1196141cc406Sopenharmony_ci  if (!test_device->val[opt_string_constraint_string_list].s)
1197141cc406Sopenharmony_ci    goto fail;
1198141cc406Sopenharmony_ci  strcpy (test_device->val[opt_string_constraint_string_list].s,
1199141cc406Sopenharmony_ci	  init_string_constraint_string_list);
1200141cc406Sopenharmony_ci
1201141cc406Sopenharmony_ci  /* opt_string_constraint_long_string_list */
1202141cc406Sopenharmony_ci  od = &test_device->opt[opt_string_constraint_long_string_list];
1203141cc406Sopenharmony_ci  od->name = "string-constraint-long-string-list";
1204141cc406Sopenharmony_ci  od->title = SANE_I18N ("(3/3) String constraint long string list");
1205141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(3/3) String test option with string list "
1206141cc406Sopenharmony_ci			"constraint. Contains some more entries...");
1207141cc406Sopenharmony_ci  od->type = SANE_TYPE_STRING;
1208141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1209141cc406Sopenharmony_ci  od->size = (SANE_Int) max_string_size (string_constraint_long_string_list);
1210141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1211141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1212141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1213141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_STRING_LIST;
1214141cc406Sopenharmony_ci  od->constraint.string_list = string_constraint_long_string_list;
1215141cc406Sopenharmony_ci  test_device->val[opt_string_constraint_long_string_list].s =
1216141cc406Sopenharmony_ci    malloc ((size_t) od->size);
1217141cc406Sopenharmony_ci  if (!test_device->val[opt_string_constraint_long_string_list].s)
1218141cc406Sopenharmony_ci    goto fail;
1219141cc406Sopenharmony_ci  strcpy (test_device->val[opt_string_constraint_long_string_list].s,
1220141cc406Sopenharmony_ci	  init_string_constraint_long_string_list);
1221141cc406Sopenharmony_ci
1222141cc406Sopenharmony_ci  /* opt_button_group */
1223141cc406Sopenharmony_ci  od = &test_device->opt[opt_button_group];
1224141cc406Sopenharmony_ci  od->name = "";
1225141cc406Sopenharmony_ci  od->title = SANE_I18N ("Button test options");
1226141cc406Sopenharmony_ci  od->desc = "";
1227141cc406Sopenharmony_ci  od->type = SANE_TYPE_GROUP;
1228141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1229141cc406Sopenharmony_ci  od->size = 0;
1230141cc406Sopenharmony_ci  od->cap = 0;
1231141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1232141cc406Sopenharmony_ci  od->constraint.range = 0;
1233141cc406Sopenharmony_ci  test_device->val[opt_button_group].w = 0;
1234141cc406Sopenharmony_ci
1235141cc406Sopenharmony_ci  /* opt_button */
1236141cc406Sopenharmony_ci  od = &test_device->opt[opt_button];
1237141cc406Sopenharmony_ci  od->name = "button";
1238141cc406Sopenharmony_ci  od->title = SANE_I18N ("(1/1) Button");
1239141cc406Sopenharmony_ci  od->desc = SANE_I18N ("(1/1) Button test option. Prints some text...");
1240141cc406Sopenharmony_ci  od->type = SANE_TYPE_BUTTON;
1241141cc406Sopenharmony_ci  od->unit = SANE_UNIT_NONE;
1242141cc406Sopenharmony_ci  od->size = 0;
1243141cc406Sopenharmony_ci  od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
1244141cc406Sopenharmony_ci  if (init_enable_test_options == SANE_FALSE)
1245141cc406Sopenharmony_ci    od->cap |= SANE_CAP_INACTIVE;
1246141cc406Sopenharmony_ci  od->constraint_type = SANE_CONSTRAINT_NONE;
1247141cc406Sopenharmony_ci  od->constraint.string_list = 0;
1248141cc406Sopenharmony_ci  test_device->val[opt_button].w = 0;
1249141cc406Sopenharmony_ci
1250141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1251141cc406Sopenharmony_ci
1252141cc406Sopenharmony_cifail:
1253141cc406Sopenharmony_ci  cleanup_options (test_device);
1254141cc406Sopenharmony_ci  return SANE_STATUS_NO_MEM;
1255141cc406Sopenharmony_ci}
1256141cc406Sopenharmony_ci
1257141cc406Sopenharmony_cistatic void
1258141cc406Sopenharmony_cicleanup_initial_string_values ()
1259141cc406Sopenharmony_ci{
1260141cc406Sopenharmony_ci  // Cleanup backing memory for initial values of string options.
1261141cc406Sopenharmony_ci  free (init_mode);
1262141cc406Sopenharmony_ci  init_mode = NULL;
1263141cc406Sopenharmony_ci  free (init_three_pass_order);
1264141cc406Sopenharmony_ci  init_three_pass_order = NULL;
1265141cc406Sopenharmony_ci  free (init_scan_source);
1266141cc406Sopenharmony_ci  init_scan_source = NULL;
1267141cc406Sopenharmony_ci  free (init_test_picture);
1268141cc406Sopenharmony_ci  init_test_picture = NULL;
1269141cc406Sopenharmony_ci  free (init_read_status_code);
1270141cc406Sopenharmony_ci  init_read_status_code = NULL;
1271141cc406Sopenharmony_ci  free (init_string);
1272141cc406Sopenharmony_ci  init_string = NULL;
1273141cc406Sopenharmony_ci  free (init_string_constraint_string_list);
1274141cc406Sopenharmony_ci  init_string_constraint_string_list = NULL;
1275141cc406Sopenharmony_ci  free (init_string_constraint_long_string_list);
1276141cc406Sopenharmony_ci  init_string_constraint_long_string_list = NULL;
1277141cc406Sopenharmony_ci}
1278141cc406Sopenharmony_ci
1279141cc406Sopenharmony_cistatic void
1280141cc406Sopenharmony_cicleanup_test_device (Test_Device * test_device)
1281141cc406Sopenharmony_ci{
1282141cc406Sopenharmony_ci  DBG (2, "cleanup_test_device: test_device=%p\n", (void *) test_device);
1283141cc406Sopenharmony_ci  if (test_device->options_initialized)
1284141cc406Sopenharmony_ci    cleanup_options (test_device);
1285141cc406Sopenharmony_ci  if (test_device->name)
1286141cc406Sopenharmony_ci    free (test_device->name);
1287141cc406Sopenharmony_ci  free (test_device);
1288141cc406Sopenharmony_ci}
1289141cc406Sopenharmony_ci
1290141cc406Sopenharmony_cistatic SANE_Status
1291141cc406Sopenharmony_ciread_option (SANE_String line, SANE_String option_string,
1292141cc406Sopenharmony_ci	     parameter_type p_type, void *value)
1293141cc406Sopenharmony_ci{
1294141cc406Sopenharmony_ci  SANE_String_Const cp;
1295141cc406Sopenharmony_ci  SANE_Char *word, *end;
1296141cc406Sopenharmony_ci
1297141cc406Sopenharmony_ci  word = 0;
1298141cc406Sopenharmony_ci
1299141cc406Sopenharmony_ci  cp = sanei_config_get_string (line, &word);
1300141cc406Sopenharmony_ci
1301141cc406Sopenharmony_ci  if (!word)
1302141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
1303141cc406Sopenharmony_ci
1304141cc406Sopenharmony_ci  if (strcmp (word, option_string) != 0)
1305141cc406Sopenharmony_ci    {
1306141cc406Sopenharmony_ci      free(word);
1307141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1308141cc406Sopenharmony_ci    }
1309141cc406Sopenharmony_ci
1310141cc406Sopenharmony_ci  free (word);
1311141cc406Sopenharmony_ci  word = 0;
1312141cc406Sopenharmony_ci
1313141cc406Sopenharmony_ci  switch (p_type)
1314141cc406Sopenharmony_ci    {
1315141cc406Sopenharmony_ci    case param_none:
1316141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
1317141cc406Sopenharmony_ci    case param_bool:
1318141cc406Sopenharmony_ci      {
1319141cc406Sopenharmony_ci	cp = sanei_config_get_string (cp, &word);
1320141cc406Sopenharmony_ci	if (!word)
1321141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1322141cc406Sopenharmony_ci	if (strlen (word) == 0)
1323141cc406Sopenharmony_ci	  {
1324141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s' requires parameter\n",
1325141cc406Sopenharmony_ci		 option_string);
1326141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1327141cc406Sopenharmony_ci	  }
1328141cc406Sopenharmony_ci	if (strcmp (word, "true") != 0 && strcmp (word, "false") != 0)
1329141cc406Sopenharmony_ci	  {
1330141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s' requires parameter "
1331141cc406Sopenharmony_ci		 "`true' or `false'\n", option_string);
1332141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1333141cc406Sopenharmony_ci	  }
1334141cc406Sopenharmony_ci	else if (strcmp (word, "true") == 0)
1335141cc406Sopenharmony_ci	  *(SANE_Bool *) value = SANE_TRUE;
1336141cc406Sopenharmony_ci	else
1337141cc406Sopenharmony_ci	  *(SANE_Bool *) value = SANE_FALSE;
1338141cc406Sopenharmony_ci	DBG (3, "read_option: set option `%s' to %s\n", option_string,
1339141cc406Sopenharmony_ci	     *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
1340141cc406Sopenharmony_ci	break;
1341141cc406Sopenharmony_ci      }
1342141cc406Sopenharmony_ci    case param_int:
1343141cc406Sopenharmony_ci      {
1344141cc406Sopenharmony_ci	SANE_Int int_value;
1345141cc406Sopenharmony_ci
1346141cc406Sopenharmony_ci	cp = sanei_config_get_string (cp, &word);
1347141cc406Sopenharmony_ci	if (!word)
1348141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1349141cc406Sopenharmony_ci	errno = 0;
1350141cc406Sopenharmony_ci	int_value = (SANE_Int) strtol (word, &end, 0);
1351141cc406Sopenharmony_ci	if (end == word)
1352141cc406Sopenharmony_ci	  {
1353141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s' requires parameter\n",
1354141cc406Sopenharmony_ci		 option_string);
1355141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1356141cc406Sopenharmony_ci	  }
1357141cc406Sopenharmony_ci	else if (errno)
1358141cc406Sopenharmony_ci	  {
1359141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s': can't parse parameter `%s' "
1360141cc406Sopenharmony_ci		 "(%s)\n", option_string, word, strerror (errno));
1361141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1362141cc406Sopenharmony_ci	  }
1363141cc406Sopenharmony_ci	else
1364141cc406Sopenharmony_ci	  {
1365141cc406Sopenharmony_ci	    DBG (3, "read_option: set option `%s' to %d\n", option_string,
1366141cc406Sopenharmony_ci		 int_value);
1367141cc406Sopenharmony_ci	    *(SANE_Int *) value = int_value;
1368141cc406Sopenharmony_ci	  }
1369141cc406Sopenharmony_ci	break;
1370141cc406Sopenharmony_ci      }
1371141cc406Sopenharmony_ci    case param_fixed:
1372141cc406Sopenharmony_ci      {
1373141cc406Sopenharmony_ci	double double_value;
1374141cc406Sopenharmony_ci	SANE_Fixed fixed_value;
1375141cc406Sopenharmony_ci
1376141cc406Sopenharmony_ci	cp = sanei_config_get_string (cp, &word);
1377141cc406Sopenharmony_ci	if (!word)
1378141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1379141cc406Sopenharmony_ci	errno = 0;
1380141cc406Sopenharmony_ci	double_value = strtod (word, &end);
1381141cc406Sopenharmony_ci	if (end == word)
1382141cc406Sopenharmony_ci	  {
1383141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s' requires parameter\n",
1384141cc406Sopenharmony_ci		 option_string);
1385141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1386141cc406Sopenharmony_ci	  }
1387141cc406Sopenharmony_ci	else if (errno)
1388141cc406Sopenharmony_ci	  {
1389141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s': can't parse parameter `%s' "
1390141cc406Sopenharmony_ci		 "(%s)\n", option_string, word, strerror (errno));
1391141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1392141cc406Sopenharmony_ci	  }
1393141cc406Sopenharmony_ci	else
1394141cc406Sopenharmony_ci	  {
1395141cc406Sopenharmony_ci	    DBG (3, "read_option: set option `%s' to %.0f\n", option_string,
1396141cc406Sopenharmony_ci		 double_value);
1397141cc406Sopenharmony_ci	    fixed_value = SANE_FIX (double_value);
1398141cc406Sopenharmony_ci	    *(SANE_Fixed *) value = fixed_value;
1399141cc406Sopenharmony_ci	  }
1400141cc406Sopenharmony_ci	break;
1401141cc406Sopenharmony_ci      }
1402141cc406Sopenharmony_ci    case param_string:
1403141cc406Sopenharmony_ci      {
1404141cc406Sopenharmony_ci	cp = sanei_config_get_string (cp, &word);
1405141cc406Sopenharmony_ci	if (!word)
1406141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1407141cc406Sopenharmony_ci	if (strlen (word) == 0)
1408141cc406Sopenharmony_ci	  {
1409141cc406Sopenharmony_ci	    DBG (3, "read_option: option `%s' requires parameter\n",
1410141cc406Sopenharmony_ci		 option_string);
1411141cc406Sopenharmony_ci	    return SANE_STATUS_INVAL;
1412141cc406Sopenharmony_ci	  }
1413141cc406Sopenharmony_ci	else
1414141cc406Sopenharmony_ci	  {
1415141cc406Sopenharmony_ci	    DBG (3, "read_option: set option `%s' to `%s'\n", option_string,
1416141cc406Sopenharmony_ci		 word);
1417141cc406Sopenharmony_ci	    if (*(SANE_String *) value)
1418141cc406Sopenharmony_ci	      free (*(SANE_String *) value);
1419141cc406Sopenharmony_ci	    *(SANE_String *) value = strdup (word);
1420141cc406Sopenharmony_ci	    if (!*(SANE_String *) value)
1421141cc406Sopenharmony_ci	      return SANE_STATUS_NO_MEM;
1422141cc406Sopenharmony_ci	  }
1423141cc406Sopenharmony_ci	break;
1424141cc406Sopenharmony_ci      }
1425141cc406Sopenharmony_ci    default:
1426141cc406Sopenharmony_ci      DBG (1, "read_option: unknown param_type %d\n", p_type);
1427141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1428141cc406Sopenharmony_ci    }				/* switch */
1429141cc406Sopenharmony_ci
1430141cc406Sopenharmony_ci  if (word)
1431141cc406Sopenharmony_ci    free (word);
1432141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1433141cc406Sopenharmony_ci}
1434141cc406Sopenharmony_ci
1435141cc406Sopenharmony_cistatic SANE_Status
1436141cc406Sopenharmony_cireader_process (Test_Device * test_device, SANE_Int fd)
1437141cc406Sopenharmony_ci{
1438141cc406Sopenharmony_ci  SANE_Status status;
1439141cc406Sopenharmony_ci  size_t byte_count = 0;
1440141cc406Sopenharmony_ci  size_t bytes_total;
1441141cc406Sopenharmony_ci  SANE_Byte *buffer = 0;
1442141cc406Sopenharmony_ci  ssize_t bytes_written = 0;
1443141cc406Sopenharmony_ci  size_t buffer_size = 0, write_count = 0;
1444141cc406Sopenharmony_ci
1445141cc406Sopenharmony_ci  DBG (2, "(child) reader_process: test_device=%p, fd=%d\n",
1446141cc406Sopenharmony_ci       (void *) test_device, fd);
1447141cc406Sopenharmony_ci
1448141cc406Sopenharmony_ci  bytes_total = (size_t) test_device->lines * (size_t) test_device->bytes_per_line;
1449141cc406Sopenharmony_ci  status = init_picture_buffer (test_device, &buffer, &buffer_size);
1450141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1451141cc406Sopenharmony_ci    return status;
1452141cc406Sopenharmony_ci
1453141cc406Sopenharmony_ci  DBG (2, "(child) reader_process: buffer=%p, buffersize=%lu\n",
1454141cc406Sopenharmony_ci       (void *) buffer, (u_long) buffer_size);
1455141cc406Sopenharmony_ci
1456141cc406Sopenharmony_ci  while (byte_count < bytes_total)
1457141cc406Sopenharmony_ci    {
1458141cc406Sopenharmony_ci      if (write_count == 0)
1459141cc406Sopenharmony_ci	{
1460141cc406Sopenharmony_ci	  write_count = buffer_size;
1461141cc406Sopenharmony_ci	  if (byte_count + (size_t) write_count > bytes_total)
1462141cc406Sopenharmony_ci	    write_count = (size_t) bytes_total - (size_t) byte_count;
1463141cc406Sopenharmony_ci
1464141cc406Sopenharmony_ci	  if (test_device->val[opt_read_delay].w == SANE_TRUE)
1465141cc406Sopenharmony_ci	    usleep ((useconds_t) test_device->val[opt_read_delay_duration].w);
1466141cc406Sopenharmony_ci	}
1467141cc406Sopenharmony_ci      bytes_written = write (fd, buffer, write_count);
1468141cc406Sopenharmony_ci      if (bytes_written < 0)
1469141cc406Sopenharmony_ci	{
1470141cc406Sopenharmony_ci	  DBG (1, "(child) reader_process: write returned %s\n",
1471141cc406Sopenharmony_ci	       strerror (errno));
1472141cc406Sopenharmony_ci	  return SANE_STATUS_IO_ERROR;
1473141cc406Sopenharmony_ci	}
1474141cc406Sopenharmony_ci      byte_count += (size_t) bytes_written;
1475141cc406Sopenharmony_ci      DBG (4, "(child) reader_process: wrote %ld bytes of %lu (%zu total)\n",
1476141cc406Sopenharmony_ci	   bytes_written, write_count, byte_count);
1477141cc406Sopenharmony_ci      write_count -= (size_t) bytes_written;
1478141cc406Sopenharmony_ci    }
1479141cc406Sopenharmony_ci
1480141cc406Sopenharmony_ci  free (buffer);
1481141cc406Sopenharmony_ci
1482141cc406Sopenharmony_ci  if (sanei_thread_is_forked ())
1483141cc406Sopenharmony_ci    {
1484141cc406Sopenharmony_ci	  DBG (4, "(child) reader_process: finished,  wrote %zu bytes, expected %zu "
1485141cc406Sopenharmony_ci       "bytes, now waiting\n", byte_count, bytes_total);
1486141cc406Sopenharmony_ci	  while (SANE_TRUE)
1487141cc406Sopenharmony_ci	    sleep (10);
1488141cc406Sopenharmony_ci	  DBG (4, "(child) reader_process: this should have never happened...");
1489141cc406Sopenharmony_ci	  close (fd);
1490141cc406Sopenharmony_ci    }
1491141cc406Sopenharmony_ci  else
1492141cc406Sopenharmony_ci    {
1493141cc406Sopenharmony_ci	  DBG (4, "(child) reader_process: finished,  wrote %zu bytes, expected %zu "
1494141cc406Sopenharmony_ci       "bytes\n", byte_count, bytes_total);
1495141cc406Sopenharmony_ci    }
1496141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1497141cc406Sopenharmony_ci}
1498141cc406Sopenharmony_ci
1499141cc406Sopenharmony_ci/*
1500141cc406Sopenharmony_ci * this code either runs in child or thread context...
1501141cc406Sopenharmony_ci */
1502141cc406Sopenharmony_cistatic int
1503141cc406Sopenharmony_cireader_task (void *data)
1504141cc406Sopenharmony_ci{
1505141cc406Sopenharmony_ci  SANE_Status status;
1506141cc406Sopenharmony_ci  struct SIGACTION act;
1507141cc406Sopenharmony_ci  struct Test_Device *test_device = (struct Test_Device *) data;
1508141cc406Sopenharmony_ci
1509141cc406Sopenharmony_ci  DBG (2, "reader_task started\n");
1510141cc406Sopenharmony_ci  if (sanei_thread_is_forked ())
1511141cc406Sopenharmony_ci    {
1512141cc406Sopenharmony_ci      DBG (3, "reader_task started (forked)\n");
1513141cc406Sopenharmony_ci      close (test_device->pipe);
1514141cc406Sopenharmony_ci      test_device->pipe = -1;
1515141cc406Sopenharmony_ci
1516141cc406Sopenharmony_ci    }
1517141cc406Sopenharmony_ci  else
1518141cc406Sopenharmony_ci    {
1519141cc406Sopenharmony_ci      DBG (3, "reader_task started (as thread)\n");
1520141cc406Sopenharmony_ci    }
1521141cc406Sopenharmony_ci
1522141cc406Sopenharmony_ci  memset (&act, 0, sizeof (act));
1523141cc406Sopenharmony_ci  sigaction (SIGTERM, &act, 0);
1524141cc406Sopenharmony_ci
1525141cc406Sopenharmony_ci  status = reader_process (test_device, test_device->reader_fds);
1526141cc406Sopenharmony_ci  DBG (2, "(child) reader_task: reader_process finished (%s)\n",
1527141cc406Sopenharmony_ci       sane_strstatus (status));
1528141cc406Sopenharmony_ci  return (int) status;
1529141cc406Sopenharmony_ci}
1530141cc406Sopenharmony_ci
1531141cc406Sopenharmony_cistatic SANE_Status
1532141cc406Sopenharmony_cifinish_pass (Test_Device * test_device)
1533141cc406Sopenharmony_ci{
1534141cc406Sopenharmony_ci  SANE_Status return_status = SANE_STATUS_GOOD;
1535141cc406Sopenharmony_ci
1536141cc406Sopenharmony_ci  DBG (2, "finish_pass: test_device=%p\n", (void *) test_device);
1537141cc406Sopenharmony_ci  test_device->scanning = SANE_FALSE;
1538141cc406Sopenharmony_ci  if (test_device->pipe >= 0)
1539141cc406Sopenharmony_ci    {
1540141cc406Sopenharmony_ci      DBG (2, "finish_pass: closing pipe\n");
1541141cc406Sopenharmony_ci      close (test_device->pipe);
1542141cc406Sopenharmony_ci      DBG (2, "finish_pass: pipe closed\n");
1543141cc406Sopenharmony_ci      test_device->pipe = -1;
1544141cc406Sopenharmony_ci    }
1545141cc406Sopenharmony_ci  if (sanei_thread_is_valid (test_device->reader_pid))
1546141cc406Sopenharmony_ci    {
1547141cc406Sopenharmony_ci      int status;
1548141cc406Sopenharmony_ci      SANE_Pid pid;
1549141cc406Sopenharmony_ci
1550141cc406Sopenharmony_ci      DBG (2, "finish_pass: terminating reader process %ld\n",
1551141cc406Sopenharmony_ci	   (long) test_device->reader_pid);
1552141cc406Sopenharmony_ci      sanei_thread_kill (test_device->reader_pid);
1553141cc406Sopenharmony_ci      pid = sanei_thread_waitpid (test_device->reader_pid, &status);
1554141cc406Sopenharmony_ci      if (!sanei_thread_is_valid (pid))
1555141cc406Sopenharmony_ci	{
1556141cc406Sopenharmony_ci	  DBG (1,
1557141cc406Sopenharmony_ci	       "finish_pass: sanei_thread_waitpid failed, already terminated? (%s)\n",
1558141cc406Sopenharmony_ci	       strerror (errno));
1559141cc406Sopenharmony_ci	}
1560141cc406Sopenharmony_ci      else
1561141cc406Sopenharmony_ci	{
1562141cc406Sopenharmony_ci	  DBG (2, "finish_pass: reader process terminated with status: %s\n",
1563141cc406Sopenharmony_ci	       sane_strstatus (status));
1564141cc406Sopenharmony_ci	}
1565141cc406Sopenharmony_ci      sanei_thread_invalidate (test_device->reader_pid);
1566141cc406Sopenharmony_ci    }
1567141cc406Sopenharmony_ci  /* this happens when running in thread context... */
1568141cc406Sopenharmony_ci  if (test_device->reader_fds >= 0)
1569141cc406Sopenharmony_ci    {
1570141cc406Sopenharmony_ci      DBG (2, "finish_pass: closing reader pipe\n");
1571141cc406Sopenharmony_ci      close (test_device->reader_fds);
1572141cc406Sopenharmony_ci      DBG (2, "finish_pass: reader pipe closed\n");
1573141cc406Sopenharmony_ci      test_device->reader_fds = -1;
1574141cc406Sopenharmony_ci    }
1575141cc406Sopenharmony_ci  return return_status;
1576141cc406Sopenharmony_ci}
1577141cc406Sopenharmony_ci
1578141cc406Sopenharmony_cistatic void
1579141cc406Sopenharmony_ciprint_options (Test_Device * test_device)
1580141cc406Sopenharmony_ci{
1581141cc406Sopenharmony_ci  SANE_Option_Descriptor *od;
1582141cc406Sopenharmony_ci  SANE_Word option_number;
1583141cc406Sopenharmony_ci  SANE_Char caps[1024];
1584141cc406Sopenharmony_ci
1585141cc406Sopenharmony_ci  for (option_number = 0; option_number < num_options; option_number++)
1586141cc406Sopenharmony_ci    {
1587141cc406Sopenharmony_ci      od = &test_device->opt[option_number];
1588141cc406Sopenharmony_ci      DBG (0, "-----> number: %d\n", option_number);
1589141cc406Sopenharmony_ci      DBG (0, "         name: `%s'\n", od->name);
1590141cc406Sopenharmony_ci      DBG (0, "        title: `%s'\n", od->title);
1591141cc406Sopenharmony_ci      DBG (0, "  description: `%s'\n", od->desc);
1592141cc406Sopenharmony_ci      DBG (0, "         type: %s\n",
1593141cc406Sopenharmony_ci	   od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" :
1594141cc406Sopenharmony_ci	   od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" :
1595141cc406Sopenharmony_ci	   od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" :
1596141cc406Sopenharmony_ci	   od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" :
1597141cc406Sopenharmony_ci	   od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" :
1598141cc406Sopenharmony_ci	   od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown");
1599141cc406Sopenharmony_ci      DBG (0, "         unit: %s\n",
1600141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" :
1601141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" :
1602141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" :
1603141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" :
1604141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" :
1605141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" :
1606141cc406Sopenharmony_ci	   od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" :
1607141cc406Sopenharmony_ci	   "unknown");
1608141cc406Sopenharmony_ci      DBG (0, "         size: %d\n", od->size);
1609141cc406Sopenharmony_ci      caps[0] = '\0';
1610141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_SOFT_SELECT)
1611141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_SOFT_SELECT ");
1612141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_HARD_SELECT)
1613141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_HARD_SELECT ");
1614141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_SOFT_DETECT)
1615141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_SOFT_DETECT ");
1616141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_EMULATED)
1617141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_EMULATED ");
1618141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_AUTOMATIC)
1619141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_AUTOMATIC ");
1620141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_INACTIVE)
1621141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_INACTIVE ");
1622141cc406Sopenharmony_ci      if (od->cap & SANE_CAP_ADVANCED)
1623141cc406Sopenharmony_ci	strcat (caps, "SANE_CAP_ADVANCED ");
1624141cc406Sopenharmony_ci      DBG (0, " capabilities: %s\n", caps);
1625141cc406Sopenharmony_ci      DBG (0, "constraint type: %s\n",
1626141cc406Sopenharmony_ci	   od->constraint_type == SANE_CONSTRAINT_NONE ?
1627141cc406Sopenharmony_ci	   "SANE_CONSTRAINT_NONE" :
1628141cc406Sopenharmony_ci	   od->constraint_type == SANE_CONSTRAINT_RANGE ?
1629141cc406Sopenharmony_ci	   "SANE_CONSTRAINT_RANGE" :
1630141cc406Sopenharmony_ci	   od->constraint_type == SANE_CONSTRAINT_WORD_LIST ?
1631141cc406Sopenharmony_ci	   "SANE_CONSTRAINT_WORD_LIST" :
1632141cc406Sopenharmony_ci	   od->constraint_type == SANE_CONSTRAINT_STRING_LIST ?
1633141cc406Sopenharmony_ci	   "SANE_CONSTRAINT_STRING_LIST" : "unknown");
1634141cc406Sopenharmony_ci    }
1635141cc406Sopenharmony_ci}
1636141cc406Sopenharmony_ci
1637141cc406Sopenharmony_ci/***************************** SANE API ****************************/
1638141cc406Sopenharmony_ci
1639141cc406Sopenharmony_ci
1640141cc406Sopenharmony_ciSANE_Status
1641141cc406Sopenharmony_cisane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_unused__ authorize)
1642141cc406Sopenharmony_ci{
1643141cc406Sopenharmony_ci  FILE *fp;
1644141cc406Sopenharmony_ci  SANE_Int linenumber;
1645141cc406Sopenharmony_ci  SANE_Char line[PATH_MAX], *word = NULL;
1646141cc406Sopenharmony_ci  SANE_String_Const cp;
1647141cc406Sopenharmony_ci  SANE_Device *sane_device;
1648141cc406Sopenharmony_ci  Test_Device *test_device, *previous_device;
1649141cc406Sopenharmony_ci  SANE_Int num;
1650141cc406Sopenharmony_ci
1651141cc406Sopenharmony_ci  DBG_INIT ();
1652141cc406Sopenharmony_ci  sanei_thread_init ();
1653141cc406Sopenharmony_ci
1654141cc406Sopenharmony_ci  test_device = 0;
1655141cc406Sopenharmony_ci  previous_device = 0;
1656141cc406Sopenharmony_ci
1657141cc406Sopenharmony_ci  DBG (1, "sane_init: SANE test backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR,
1658141cc406Sopenharmony_ci       SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
1659141cc406Sopenharmony_ci
1660141cc406Sopenharmony_ci  if (version_code)
1661141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
1662141cc406Sopenharmony_ci
1663141cc406Sopenharmony_ci  if (inited)
1664141cc406Sopenharmony_ci    DBG (3, "sane_init: warning: already inited\n");
1665141cc406Sopenharmony_ci
1666141cc406Sopenharmony_ci  // Setup initial values of string options. Call free initially in case we've
1667141cc406Sopenharmony_ci  // already called sane_init and these values are already non-null.
1668141cc406Sopenharmony_ci  free (init_mode);
1669141cc406Sopenharmony_ci  init_mode = strdup (SANE_VALUE_SCAN_MODE_GRAY);
1670141cc406Sopenharmony_ci  if (!init_mode)
1671141cc406Sopenharmony_ci    goto fail;
1672141cc406Sopenharmony_ci
1673141cc406Sopenharmony_ci  free (init_three_pass_order);
1674141cc406Sopenharmony_ci  init_three_pass_order = strdup ("RGB");
1675141cc406Sopenharmony_ci  if (!init_three_pass_order)
1676141cc406Sopenharmony_ci    goto fail;
1677141cc406Sopenharmony_ci
1678141cc406Sopenharmony_ci  free (init_scan_source);
1679141cc406Sopenharmony_ci  init_scan_source = strdup ("Flatbed");
1680141cc406Sopenharmony_ci  if (!init_scan_source)
1681141cc406Sopenharmony_ci    goto fail;
1682141cc406Sopenharmony_ci
1683141cc406Sopenharmony_ci  free (init_test_picture);
1684141cc406Sopenharmony_ci  init_test_picture = strdup ("Solid black");
1685141cc406Sopenharmony_ci  if (!init_test_picture)
1686141cc406Sopenharmony_ci    goto fail;
1687141cc406Sopenharmony_ci
1688141cc406Sopenharmony_ci  free (init_read_status_code);
1689141cc406Sopenharmony_ci  init_read_status_code = strdup ("Default");
1690141cc406Sopenharmony_ci  if (!init_read_status_code)
1691141cc406Sopenharmony_ci    goto fail;
1692141cc406Sopenharmony_ci
1693141cc406Sopenharmony_ci  free (init_string);
1694141cc406Sopenharmony_ci  init_string = strdup ("This is the contents of the string option. "
1695141cc406Sopenharmony_ci    "Fill some more words to see how the frontend behaves.");
1696141cc406Sopenharmony_ci  if (!init_string)
1697141cc406Sopenharmony_ci    goto fail;
1698141cc406Sopenharmony_ci
1699141cc406Sopenharmony_ci  free (init_string_constraint_string_list);
1700141cc406Sopenharmony_ci  init_string_constraint_string_list = strdup ("First entry");
1701141cc406Sopenharmony_ci  if (!init_string_constraint_string_list)
1702141cc406Sopenharmony_ci    goto fail;
1703141cc406Sopenharmony_ci
1704141cc406Sopenharmony_ci  free (init_string_constraint_long_string_list);
1705141cc406Sopenharmony_ci  init_string_constraint_long_string_list = strdup ("First entry");
1706141cc406Sopenharmony_ci  if (!init_string_constraint_long_string_list)
1707141cc406Sopenharmony_ci    goto fail;
1708141cc406Sopenharmony_ci
1709141cc406Sopenharmony_ci  fp = sanei_config_open (TEST_CONFIG_FILE);
1710141cc406Sopenharmony_ci  if (fp)
1711141cc406Sopenharmony_ci    {
1712141cc406Sopenharmony_ci      linenumber = 0;
1713141cc406Sopenharmony_ci      DBG (4, "sane_init: reading config file `%s'\n", TEST_CONFIG_FILE);
1714141cc406Sopenharmony_ci      while (sanei_config_read (line, sizeof (line), fp))
1715141cc406Sopenharmony_ci	{
1716141cc406Sopenharmony_ci	  if (word)
1717141cc406Sopenharmony_ci	    free (word);
1718141cc406Sopenharmony_ci	  word = NULL;
1719141cc406Sopenharmony_ci	  linenumber++;
1720141cc406Sopenharmony_ci
1721141cc406Sopenharmony_ci	  cp = sanei_config_get_string (line, &word);
1722141cc406Sopenharmony_ci	  if (!word || cp == line)
1723141cc406Sopenharmony_ci	    {
1724141cc406Sopenharmony_ci	      DBG (5,
1725141cc406Sopenharmony_ci		   "sane_init: config file line %3d: ignoring empty line\n",
1726141cc406Sopenharmony_ci		   linenumber);
1727141cc406Sopenharmony_ci	      continue;
1728141cc406Sopenharmony_ci	    }
1729141cc406Sopenharmony_ci	  if (word[0] == '#')
1730141cc406Sopenharmony_ci	    {
1731141cc406Sopenharmony_ci	      DBG (5,
1732141cc406Sopenharmony_ci		   "sane_init: config file line %3d: ignoring comment line\n",
1733141cc406Sopenharmony_ci		   linenumber);
1734141cc406Sopenharmony_ci	      continue;
1735141cc406Sopenharmony_ci	    }
1736141cc406Sopenharmony_ci
1737141cc406Sopenharmony_ci	  DBG (5, "sane_init: config file line %3d: `%s'\n",
1738141cc406Sopenharmony_ci	       linenumber, line);
1739141cc406Sopenharmony_ci	  if (read_option (line, "number_of_devices", param_int,
1740141cc406Sopenharmony_ci			   &init_number_of_devices) == SANE_STATUS_GOOD)
1741141cc406Sopenharmony_ci	    continue;
1742141cc406Sopenharmony_ci	  if (read_option (line, "mode", param_string,
1743141cc406Sopenharmony_ci			   &init_mode) == SANE_STATUS_GOOD)
1744141cc406Sopenharmony_ci	    continue;
1745141cc406Sopenharmony_ci	  if (read_option (line, "hand-scanner", param_bool,
1746141cc406Sopenharmony_ci			   &init_hand_scanner) == SANE_STATUS_GOOD)
1747141cc406Sopenharmony_ci	    continue;
1748141cc406Sopenharmony_ci	  if (read_option (line, "three-pass", param_bool,
1749141cc406Sopenharmony_ci			   &init_three_pass) == SANE_STATUS_GOOD)
1750141cc406Sopenharmony_ci	    continue;
1751141cc406Sopenharmony_ci	  if (read_option (line, "three-pass-order", param_string,
1752141cc406Sopenharmony_ci			   &init_three_pass_order) == SANE_STATUS_GOOD)
1753141cc406Sopenharmony_ci	    continue;
1754141cc406Sopenharmony_ci	  if (read_option (line, "resolution_min", param_fixed,
1755141cc406Sopenharmony_ci			   &resolution_range.min) == SANE_STATUS_GOOD)
1756141cc406Sopenharmony_ci	    continue;
1757141cc406Sopenharmony_ci	  if (read_option (line, "resolution_max", param_fixed,
1758141cc406Sopenharmony_ci			   &resolution_range.max) == SANE_STATUS_GOOD)
1759141cc406Sopenharmony_ci	    continue;
1760141cc406Sopenharmony_ci	  if (read_option (line, "resolution_quant", param_fixed,
1761141cc406Sopenharmony_ci			   &resolution_range.quant) == SANE_STATUS_GOOD)
1762141cc406Sopenharmony_ci	    continue;
1763141cc406Sopenharmony_ci	  if (read_option (line, "resolution", param_fixed,
1764141cc406Sopenharmony_ci			   &init_resolution) == SANE_STATUS_GOOD)
1765141cc406Sopenharmony_ci	    continue;
1766141cc406Sopenharmony_ci	  if (read_option (line, "depth", param_int,
1767141cc406Sopenharmony_ci			   &init_depth) == SANE_STATUS_GOOD)
1768141cc406Sopenharmony_ci	    continue;
1769141cc406Sopenharmony_ci	  if (read_option (line, "scan-source", param_string,
1770141cc406Sopenharmony_ci			   &init_scan_source) == SANE_STATUS_GOOD)
1771141cc406Sopenharmony_ci	    continue;
1772141cc406Sopenharmony_ci	  if (read_option (line, "test-picture", param_string,
1773141cc406Sopenharmony_ci			   &init_test_picture) == SANE_STATUS_GOOD)
1774141cc406Sopenharmony_ci	    continue;
1775141cc406Sopenharmony_ci	  if (read_option (line, "invert-endianess", param_bool,
1776141cc406Sopenharmony_ci			   &init_invert_endianess) == SANE_STATUS_GOOD)
1777141cc406Sopenharmony_ci	    continue;
1778141cc406Sopenharmony_ci	  if (read_option (line, "read-limit", param_bool,
1779141cc406Sopenharmony_ci			   &init_read_limit) == SANE_STATUS_GOOD)
1780141cc406Sopenharmony_ci	    continue;
1781141cc406Sopenharmony_ci	  if (read_option (line, "read-limit-size", param_int,
1782141cc406Sopenharmony_ci			   &init_read_limit_size) == SANE_STATUS_GOOD)
1783141cc406Sopenharmony_ci	    continue;
1784141cc406Sopenharmony_ci	  if (read_option (line, "read-delay", param_bool,
1785141cc406Sopenharmony_ci			   &init_read_delay) == SANE_STATUS_GOOD)
1786141cc406Sopenharmony_ci	    continue;
1787141cc406Sopenharmony_ci	  if (read_option (line, "read-delay-duration", param_int,
1788141cc406Sopenharmony_ci			   &init_read_delay_duration) == SANE_STATUS_GOOD)
1789141cc406Sopenharmony_ci	    continue;
1790141cc406Sopenharmony_ci	  if (read_option (line, "read-status-code", param_string,
1791141cc406Sopenharmony_ci			   &init_read_status_code) == SANE_STATUS_GOOD)
1792141cc406Sopenharmony_ci	    continue;
1793141cc406Sopenharmony_ci	  if (read_option (line, "ppl-loss", param_int,
1794141cc406Sopenharmony_ci			   &init_ppl_loss) == SANE_STATUS_GOOD)
1795141cc406Sopenharmony_ci	    continue;
1796141cc406Sopenharmony_ci	  if (read_option (line, "fuzzy-parameters", param_bool,
1797141cc406Sopenharmony_ci			   &init_fuzzy_parameters) == SANE_STATUS_GOOD)
1798141cc406Sopenharmony_ci	    continue;
1799141cc406Sopenharmony_ci	  if (read_option (line, "non-blocking", param_bool,
1800141cc406Sopenharmony_ci			   &init_non_blocking) == SANE_STATUS_GOOD)
1801141cc406Sopenharmony_ci	    continue;
1802141cc406Sopenharmony_ci	  if (read_option (line, "select-fd", param_bool,
1803141cc406Sopenharmony_ci			   &init_select_fd) == SANE_STATUS_GOOD)
1804141cc406Sopenharmony_ci	    continue;
1805141cc406Sopenharmony_ci	  if (read_option (line, "enable-test-options", param_bool,
1806141cc406Sopenharmony_ci			   &init_enable_test_options) == SANE_STATUS_GOOD)
1807141cc406Sopenharmony_ci	    continue;
1808141cc406Sopenharmony_ci	  if (read_option (line, "geometry_min", param_fixed,
1809141cc406Sopenharmony_ci			   &geometry_range.min) == SANE_STATUS_GOOD)
1810141cc406Sopenharmony_ci	    continue;
1811141cc406Sopenharmony_ci	  if (read_option (line, "geometry_max", param_fixed,
1812141cc406Sopenharmony_ci			   &geometry_range.max) == SANE_STATUS_GOOD)
1813141cc406Sopenharmony_ci	    continue;
1814141cc406Sopenharmony_ci	  if (read_option (line, "geometry_quant", param_fixed,
1815141cc406Sopenharmony_ci			   &geometry_range.quant) == SANE_STATUS_GOOD)
1816141cc406Sopenharmony_ci	    continue;
1817141cc406Sopenharmony_ci	  if (read_option (line, "tl_x", param_fixed,
1818141cc406Sopenharmony_ci			   &init_tl_x) == SANE_STATUS_GOOD)
1819141cc406Sopenharmony_ci	    continue;
1820141cc406Sopenharmony_ci	  if (read_option (line, "tl_y", param_fixed,
1821141cc406Sopenharmony_ci			   &init_tl_y) == SANE_STATUS_GOOD)
1822141cc406Sopenharmony_ci	    continue;
1823141cc406Sopenharmony_ci	  if (read_option (line, "br_x", param_fixed,
1824141cc406Sopenharmony_ci			   &init_br_x) == SANE_STATUS_GOOD)
1825141cc406Sopenharmony_ci	    continue;
1826141cc406Sopenharmony_ci	  if (read_option (line, "br_y", param_fixed,
1827141cc406Sopenharmony_ci			   &init_br_y) == SANE_STATUS_GOOD)
1828141cc406Sopenharmony_ci	    continue;
1829141cc406Sopenharmony_ci
1830141cc406Sopenharmony_ci	  DBG (3, "sane-init: I don't know how to handle option `%s'\n",
1831141cc406Sopenharmony_ci	       word);
1832141cc406Sopenharmony_ci	}			/* while */
1833141cc406Sopenharmony_ci      if (word)
1834141cc406Sopenharmony_ci	free (word);
1835141cc406Sopenharmony_ci      fclose (fp);
1836141cc406Sopenharmony_ci    }				/* if */
1837141cc406Sopenharmony_ci  else
1838141cc406Sopenharmony_ci    {
1839141cc406Sopenharmony_ci      DBG (3, "sane_init: couldn't find config file (%s), using default "
1840141cc406Sopenharmony_ci	   "settings\n", TEST_CONFIG_FILE);
1841141cc406Sopenharmony_ci    }
1842141cc406Sopenharmony_ci
1843141cc406Sopenharmony_ci  /* create devices */
1844141cc406Sopenharmony_ci  sane_device_list =
1845141cc406Sopenharmony_ci    malloc ((size_t) (init_number_of_devices + 1) * sizeof (sane_device));
1846141cc406Sopenharmony_ci  if (!sane_device_list)
1847141cc406Sopenharmony_ci    goto fail;
1848141cc406Sopenharmony_ci  for (num = 0; num < init_number_of_devices; num++)
1849141cc406Sopenharmony_ci    {
1850141cc406Sopenharmony_ci      SANE_Char number_string[PATH_MAX];
1851141cc406Sopenharmony_ci
1852141cc406Sopenharmony_ci      test_device = calloc (sizeof (*test_device), 1);
1853141cc406Sopenharmony_ci      if (!test_device)
1854141cc406Sopenharmony_ci	goto fail_device;
1855141cc406Sopenharmony_ci      test_device->sane.vendor = "Noname";
1856141cc406Sopenharmony_ci      test_device->sane.type = "virtual device";
1857141cc406Sopenharmony_ci      test_device->sane.model = "frontend-tester";
1858141cc406Sopenharmony_ci      snprintf (number_string, sizeof (number_string), "%d", num);
1859141cc406Sopenharmony_ci      number_string[sizeof (number_string) - 1] = '\0';
1860141cc406Sopenharmony_ci      test_device->name = strdup (number_string);
1861141cc406Sopenharmony_ci      if (!test_device->name)
1862141cc406Sopenharmony_ci	goto fail_name;
1863141cc406Sopenharmony_ci      test_device->sane.name = test_device->name;
1864141cc406Sopenharmony_ci      if (previous_device)
1865141cc406Sopenharmony_ci	previous_device->next = test_device;
1866141cc406Sopenharmony_ci      previous_device = test_device;
1867141cc406Sopenharmony_ci      if (num == 0)
1868141cc406Sopenharmony_ci	first_test_device = test_device;
1869141cc406Sopenharmony_ci      sane_device_list[num] = &test_device->sane;
1870141cc406Sopenharmony_ci      test_device->open = SANE_FALSE;
1871141cc406Sopenharmony_ci      test_device->eof = SANE_FALSE;
1872141cc406Sopenharmony_ci      test_device->scanning = SANE_FALSE;
1873141cc406Sopenharmony_ci      test_device->cancelled = SANE_FALSE;
1874141cc406Sopenharmony_ci      test_device->options_initialized = SANE_FALSE;
1875141cc406Sopenharmony_ci      sanei_thread_initialize (test_device->reader_pid);
1876141cc406Sopenharmony_ci      test_device->pipe = -1;
1877141cc406Sopenharmony_ci      DBG (4, "sane_init: new device: `%s' is a %s %s %s\n",
1878141cc406Sopenharmony_ci	   test_device->sane.name, test_device->sane.vendor,
1879141cc406Sopenharmony_ci	   test_device->sane.model, test_device->sane.type);
1880141cc406Sopenharmony_ci    }
1881141cc406Sopenharmony_ci  test_device->next = 0;
1882141cc406Sopenharmony_ci  sane_device_list[num] = 0;
1883141cc406Sopenharmony_ci  srand ((unsigned int) time (NULL));
1884141cc406Sopenharmony_ci  random_factor = ((double) rand ()) / RAND_MAX + 0.5;
1885141cc406Sopenharmony_ci  inited = SANE_TRUE;
1886141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1887141cc406Sopenharmony_ci
1888141cc406Sopenharmony_cifail_name:
1889141cc406Sopenharmony_ci  // test_device refers to the last device we were creating, which has not
1890141cc406Sopenharmony_ci  // yet been added to the linked list of devices.
1891141cc406Sopenharmony_ci  free (test_device);
1892141cc406Sopenharmony_cifail_device:
1893141cc406Sopenharmony_ci  // Now, iterate through the linked list of devices to clean up any successful
1894141cc406Sopenharmony_ci  // devices.
1895141cc406Sopenharmony_ci  test_device = first_test_device;
1896141cc406Sopenharmony_ci  while (test_device)
1897141cc406Sopenharmony_ci    {
1898141cc406Sopenharmony_ci      previous_device = test_device;
1899141cc406Sopenharmony_ci      test_device = test_device->next;
1900141cc406Sopenharmony_ci      cleanup_test_device (previous_device);
1901141cc406Sopenharmony_ci    }
1902141cc406Sopenharmony_ci  free (sane_device_list);
1903141cc406Sopenharmony_cifail:
1904141cc406Sopenharmony_ci  cleanup_initial_string_values ();
1905141cc406Sopenharmony_ci  return SANE_STATUS_NO_MEM;
1906141cc406Sopenharmony_ci}
1907141cc406Sopenharmony_ci
1908141cc406Sopenharmony_civoid
1909141cc406Sopenharmony_cisane_exit (void)
1910141cc406Sopenharmony_ci{
1911141cc406Sopenharmony_ci  Test_Device *test_device, *previous_device;
1912141cc406Sopenharmony_ci
1913141cc406Sopenharmony_ci  DBG (2, "sane_exit\n");
1914141cc406Sopenharmony_ci  if (!inited)
1915141cc406Sopenharmony_ci    {
1916141cc406Sopenharmony_ci      DBG (1, "sane_exit: not inited, call sane_init() first\n");
1917141cc406Sopenharmony_ci      return;
1918141cc406Sopenharmony_ci    }
1919141cc406Sopenharmony_ci
1920141cc406Sopenharmony_ci  test_device = first_test_device;
1921141cc406Sopenharmony_ci  while (test_device)
1922141cc406Sopenharmony_ci    {
1923141cc406Sopenharmony_ci      DBG (4, "sane_exit: freeing device %s\n", test_device->name);
1924141cc406Sopenharmony_ci      previous_device = test_device;
1925141cc406Sopenharmony_ci      test_device = test_device->next;
1926141cc406Sopenharmony_ci      cleanup_test_device (previous_device);
1927141cc406Sopenharmony_ci    }
1928141cc406Sopenharmony_ci  DBG (4, "sane_exit: freeing device list\n");
1929141cc406Sopenharmony_ci  if (sane_device_list)
1930141cc406Sopenharmony_ci    free (sane_device_list);
1931141cc406Sopenharmony_ci  sane_device_list = NULL;
1932141cc406Sopenharmony_ci  first_test_device = NULL;
1933141cc406Sopenharmony_ci
1934141cc406Sopenharmony_ci  cleanup_initial_string_values ();
1935141cc406Sopenharmony_ci  inited = SANE_FALSE;
1936141cc406Sopenharmony_ci  return;
1937141cc406Sopenharmony_ci}
1938141cc406Sopenharmony_ci
1939141cc406Sopenharmony_ci
1940141cc406Sopenharmony_ciSANE_Status
1941141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1942141cc406Sopenharmony_ci{
1943141cc406Sopenharmony_ci
1944141cc406Sopenharmony_ci  DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n",
1945141cc406Sopenharmony_ci       (void *) device_list, local_only);
1946141cc406Sopenharmony_ci  if (!inited)
1947141cc406Sopenharmony_ci    {
1948141cc406Sopenharmony_ci      DBG (1, "sane_get_devices: not inited, call sane_init() first\n");
1949141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1950141cc406Sopenharmony_ci    }
1951141cc406Sopenharmony_ci
1952141cc406Sopenharmony_ci  if (!device_list)
1953141cc406Sopenharmony_ci    {
1954141cc406Sopenharmony_ci      DBG (1, "sane_get_devices: device_list == 0\n");
1955141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1956141cc406Sopenharmony_ci    }
1957141cc406Sopenharmony_ci  *device_list = (const SANE_Device **) sane_device_list;
1958141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1959141cc406Sopenharmony_ci}
1960141cc406Sopenharmony_ci
1961141cc406Sopenharmony_ciSANE_Status
1962141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
1963141cc406Sopenharmony_ci{
1964141cc406Sopenharmony_ci  Test_Device *test_device = first_test_device;
1965141cc406Sopenharmony_ci  SANE_Status status;
1966141cc406Sopenharmony_ci
1967141cc406Sopenharmony_ci  DBG (2, "sane_open: devicename = \"%s\", handle=%p\n",
1968141cc406Sopenharmony_ci       devicename, (void *) handle);
1969141cc406Sopenharmony_ci  if (!inited)
1970141cc406Sopenharmony_ci    {
1971141cc406Sopenharmony_ci      DBG (1, "sane_open: not inited, call sane_init() first\n");
1972141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1973141cc406Sopenharmony_ci    }
1974141cc406Sopenharmony_ci
1975141cc406Sopenharmony_ci  if (!handle)
1976141cc406Sopenharmony_ci    {
1977141cc406Sopenharmony_ci      DBG (1, "sane_open: handle == 0\n");
1978141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1979141cc406Sopenharmony_ci    }
1980141cc406Sopenharmony_ci
1981141cc406Sopenharmony_ci  if (!devicename || strlen (devicename) == 0)
1982141cc406Sopenharmony_ci    {
1983141cc406Sopenharmony_ci      DBG (2, "sane_open: device name NULL or empty\n");
1984141cc406Sopenharmony_ci    }
1985141cc406Sopenharmony_ci  else
1986141cc406Sopenharmony_ci    {
1987141cc406Sopenharmony_ci      for (test_device = first_test_device; test_device;
1988141cc406Sopenharmony_ci	   test_device = test_device->next)
1989141cc406Sopenharmony_ci	{
1990141cc406Sopenharmony_ci	  if (strcmp (devicename, test_device->name) == 0)
1991141cc406Sopenharmony_ci	    break;
1992141cc406Sopenharmony_ci	}
1993141cc406Sopenharmony_ci    }
1994141cc406Sopenharmony_ci  if (!test_device)
1995141cc406Sopenharmony_ci    {
1996141cc406Sopenharmony_ci      DBG (1, "sane_open: device `%s' not found\n", devicename);
1997141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1998141cc406Sopenharmony_ci    }
1999141cc406Sopenharmony_ci  if (test_device->open)
2000141cc406Sopenharmony_ci    {
2001141cc406Sopenharmony_ci      DBG (1, "sane_open: device `%s' already open\n", devicename);
2002141cc406Sopenharmony_ci      return SANE_STATUS_DEVICE_BUSY;
2003141cc406Sopenharmony_ci    }
2004141cc406Sopenharmony_ci  DBG (2, "sane_open: opening device `%s', handle = %p\n", test_device->name,
2005141cc406Sopenharmony_ci       (void *) test_device);
2006141cc406Sopenharmony_ci  test_device->open = SANE_TRUE;
2007141cc406Sopenharmony_ci  *handle = test_device;
2008141cc406Sopenharmony_ci
2009141cc406Sopenharmony_ci  if (!test_device->options_initialized) {
2010141cc406Sopenharmony_ci    status = init_options (test_device);
2011141cc406Sopenharmony_ci    if (status != SANE_STATUS_GOOD)
2012141cc406Sopenharmony_ci      return status;
2013141cc406Sopenharmony_ci    test_device->options_initialized = SANE_TRUE;
2014141cc406Sopenharmony_ci  }
2015141cc406Sopenharmony_ci
2016141cc406Sopenharmony_ci  test_device->open = SANE_TRUE;
2017141cc406Sopenharmony_ci  test_device->scanning = SANE_FALSE;
2018141cc406Sopenharmony_ci  test_device->cancelled = SANE_FALSE;
2019141cc406Sopenharmony_ci  test_device->eof = SANE_FALSE;
2020141cc406Sopenharmony_ci  test_device->bytes_total = 0;
2021141cc406Sopenharmony_ci  test_device->pass = 0;
2022141cc406Sopenharmony_ci  test_device->number_of_scans = 0;
2023141cc406Sopenharmony_ci
2024141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2025141cc406Sopenharmony_ci}
2026141cc406Sopenharmony_ci
2027141cc406Sopenharmony_civoid
2028141cc406Sopenharmony_cisane_close (SANE_Handle handle)
2029141cc406Sopenharmony_ci{
2030141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2031141cc406Sopenharmony_ci
2032141cc406Sopenharmony_ci  DBG (2, "sane_close: handle=%p\n", (void *) handle);
2033141cc406Sopenharmony_ci  if (!inited)
2034141cc406Sopenharmony_ci    {
2035141cc406Sopenharmony_ci      DBG (1, "sane_close: not inited, call sane_init() first\n");
2036141cc406Sopenharmony_ci      return;
2037141cc406Sopenharmony_ci    }
2038141cc406Sopenharmony_ci
2039141cc406Sopenharmony_ci  if (!check_handle (handle))
2040141cc406Sopenharmony_ci    {
2041141cc406Sopenharmony_ci      DBG (1, "sane_close: handle %p unknown\n", (void *) handle);
2042141cc406Sopenharmony_ci      return;
2043141cc406Sopenharmony_ci    }
2044141cc406Sopenharmony_ci  if (!test_device->open)
2045141cc406Sopenharmony_ci    {
2046141cc406Sopenharmony_ci      DBG (1, "sane_close: handle %p not open\n", (void *) handle);
2047141cc406Sopenharmony_ci      return;
2048141cc406Sopenharmony_ci    }
2049141cc406Sopenharmony_ci  test_device->open = SANE_FALSE;
2050141cc406Sopenharmony_ci  return;
2051141cc406Sopenharmony_ci}
2052141cc406Sopenharmony_ci
2053141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
2054141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2055141cc406Sopenharmony_ci{
2056141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2057141cc406Sopenharmony_ci
2058141cc406Sopenharmony_ci  DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n",
2059141cc406Sopenharmony_ci       (void *) handle, option);
2060141cc406Sopenharmony_ci  if (!inited)
2061141cc406Sopenharmony_ci    {
2062141cc406Sopenharmony_ci      DBG (1, "sane_get_option_descriptor: not inited, call sane_init() "
2063141cc406Sopenharmony_ci	   "first\n");
2064141cc406Sopenharmony_ci      return 0;
2065141cc406Sopenharmony_ci    }
2066141cc406Sopenharmony_ci
2067141cc406Sopenharmony_ci  if (!check_handle (handle))
2068141cc406Sopenharmony_ci    {
2069141cc406Sopenharmony_ci      DBG (1, "sane_get_option_descriptor: handle %p unknown\n",
2070141cc406Sopenharmony_ci	   (void *) handle);
2071141cc406Sopenharmony_ci      return 0;
2072141cc406Sopenharmony_ci    }
2073141cc406Sopenharmony_ci  if (!test_device->open)
2074141cc406Sopenharmony_ci    {
2075141cc406Sopenharmony_ci      DBG (1, "sane_get_option_descriptor: not open\n");
2076141cc406Sopenharmony_ci      return 0;
2077141cc406Sopenharmony_ci    }
2078141cc406Sopenharmony_ci  if (option < 0 || option >= num_options)
2079141cc406Sopenharmony_ci    {
2080141cc406Sopenharmony_ci      DBG (3, "sane_get_option_descriptor: option < 0 || "
2081141cc406Sopenharmony_ci	   "option > num_options\n");
2082141cc406Sopenharmony_ci      return 0;
2083141cc406Sopenharmony_ci    }
2084141cc406Sopenharmony_ci
2085141cc406Sopenharmony_ci  test_device->loaded[option] = 1;
2086141cc406Sopenharmony_ci
2087141cc406Sopenharmony_ci  return &test_device->opt[option];
2088141cc406Sopenharmony_ci}
2089141cc406Sopenharmony_ci
2090141cc406Sopenharmony_ciSANE_Status
2091141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
2092141cc406Sopenharmony_ci		     void *value, SANE_Int * info)
2093141cc406Sopenharmony_ci{
2094141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2095141cc406Sopenharmony_ci  SANE_Int myinfo = 0;
2096141cc406Sopenharmony_ci  SANE_Status status;
2097141cc406Sopenharmony_ci
2098141cc406Sopenharmony_ci  DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
2099141cc406Sopenharmony_ci       (void *) handle, option, action, (void *) value, (void *) info);
2100141cc406Sopenharmony_ci  if (!inited)
2101141cc406Sopenharmony_ci    {
2102141cc406Sopenharmony_ci      DBG (1, "sane_control_option: not inited, call sane_init() first\n");
2103141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2104141cc406Sopenharmony_ci    }
2105141cc406Sopenharmony_ci
2106141cc406Sopenharmony_ci  if (!check_handle (handle))
2107141cc406Sopenharmony_ci    {
2108141cc406Sopenharmony_ci      DBG (1, "sane_control_option: handle %p unknown\n", (void *) handle);
2109141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2110141cc406Sopenharmony_ci    }
2111141cc406Sopenharmony_ci  if (!test_device->open)
2112141cc406Sopenharmony_ci    {
2113141cc406Sopenharmony_ci      DBG (1, "sane_control_option: not open\n");
2114141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2115141cc406Sopenharmony_ci    }
2116141cc406Sopenharmony_ci  if (test_device->scanning)
2117141cc406Sopenharmony_ci    {
2118141cc406Sopenharmony_ci      DBG (1, "sane_control_option: is scanning\n");
2119141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2120141cc406Sopenharmony_ci    }
2121141cc406Sopenharmony_ci  if (option < 0 || option >= num_options)
2122141cc406Sopenharmony_ci    {
2123141cc406Sopenharmony_ci      DBG (1, "sane_control_option: option < 0 || option > num_options\n");
2124141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2125141cc406Sopenharmony_ci    }
2126141cc406Sopenharmony_ci
2127141cc406Sopenharmony_ci  if (!test_device->loaded[option])
2128141cc406Sopenharmony_ci    {
2129141cc406Sopenharmony_ci      DBG (1, "sane_control_option: option not loaded\n");
2130141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2131141cc406Sopenharmony_ci    }
2132141cc406Sopenharmony_ci
2133141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (test_device->opt[option].cap))
2134141cc406Sopenharmony_ci    {
2135141cc406Sopenharmony_ci      DBG (1, "sane_control_option: option is inactive\n");
2136141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2137141cc406Sopenharmony_ci    }
2138141cc406Sopenharmony_ci
2139141cc406Sopenharmony_ci  if (test_device->opt[option].type == SANE_TYPE_GROUP)
2140141cc406Sopenharmony_ci    {
2141141cc406Sopenharmony_ci      DBG (1, "sane_control_option: option is a group\n");
2142141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2143141cc406Sopenharmony_ci    }
2144141cc406Sopenharmony_ci
2145141cc406Sopenharmony_ci  switch (action)
2146141cc406Sopenharmony_ci    {
2147141cc406Sopenharmony_ci    case SANE_ACTION_SET_AUTO:
2148141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap))
2149141cc406Sopenharmony_ci	{
2150141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: option is not setable\n");
2151141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2152141cc406Sopenharmony_ci	}
2153141cc406Sopenharmony_ci      if (!(test_device->opt[option].cap & SANE_CAP_AUTOMATIC))
2154141cc406Sopenharmony_ci	{
2155141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: option is not automatically "
2156141cc406Sopenharmony_ci	       "setable\n");
2157141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2158141cc406Sopenharmony_ci	}
2159141cc406Sopenharmony_ci      switch (option)
2160141cc406Sopenharmony_ci	{
2161141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect_auto:
2162141cc406Sopenharmony_ci	  test_device->val[option].w = SANE_TRUE;
2163141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) automatically "
2164141cc406Sopenharmony_ci	       "to %s\n", option, test_device->opt[option].name,
2165141cc406Sopenharmony_ci	       test_device->val[option].w == SANE_TRUE ? "true" : "false");
2166141cc406Sopenharmony_ci	  break;
2167141cc406Sopenharmony_ci
2168141cc406Sopenharmony_ci	default:
2169141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: trying to automatically set "
2170141cc406Sopenharmony_ci	       "unexpected option\n");
2171141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2172141cc406Sopenharmony_ci	}
2173141cc406Sopenharmony_ci      break;
2174141cc406Sopenharmony_ci
2175141cc406Sopenharmony_ci    case SANE_ACTION_SET_VALUE:
2176141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap))
2177141cc406Sopenharmony_ci	{
2178141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: option is not setable\n");
2179141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2180141cc406Sopenharmony_ci	}
2181141cc406Sopenharmony_ci      status = sanei_constrain_value (&test_device->opt[option],
2182141cc406Sopenharmony_ci				      value, &myinfo);
2183141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2184141cc406Sopenharmony_ci	{
2185141cc406Sopenharmony_ci	  DBG (3, "sane_control_option: sanei_constrain_value returned %s\n",
2186141cc406Sopenharmony_ci	       sane_strstatus (status));
2187141cc406Sopenharmony_ci	  return status;
2188141cc406Sopenharmony_ci	}
2189141cc406Sopenharmony_ci      switch (option)
2190141cc406Sopenharmony_ci	{
2191141cc406Sopenharmony_ci	case opt_tl_x:		/* Fixed with parameter reloading */
2192141cc406Sopenharmony_ci	case opt_tl_y:
2193141cc406Sopenharmony_ci	case opt_br_x:
2194141cc406Sopenharmony_ci	case opt_br_y:
2195141cc406Sopenharmony_ci	case opt_resolution:
2196141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Fixed *) value)
2197141cc406Sopenharmony_ci	    {
2198141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2199141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2200141cc406Sopenharmony_ci	      break;
2201141cc406Sopenharmony_ci	    }
2202141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Fixed *) value;
2203141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2204141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n",
2205141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2206141cc406Sopenharmony_ci	       SANE_UNFIX (*(SANE_Fixed *) value),
2207141cc406Sopenharmony_ci	       test_device->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi");
2208141cc406Sopenharmony_ci	  break;
2209141cc406Sopenharmony_ci	case opt_fixed:	/* Fixed */
2210141cc406Sopenharmony_ci	case opt_fixed_constraint_range:
2211141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Fixed *) value)
2212141cc406Sopenharmony_ci	    {
2213141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2214141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2215141cc406Sopenharmony_ci	      break;
2216141cc406Sopenharmony_ci	    }
2217141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Fixed *) value;
2218141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %.0f\n",
2219141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2220141cc406Sopenharmony_ci	       SANE_UNFIX (*(SANE_Fixed *) value));
2221141cc406Sopenharmony_ci	  break;
2222141cc406Sopenharmony_ci	case opt_read_limit_size:	/* Int */
2223141cc406Sopenharmony_ci	case opt_ppl_loss:
2224141cc406Sopenharmony_ci	case opt_read_delay_duration:
2225141cc406Sopenharmony_ci	case opt_int:
2226141cc406Sopenharmony_ci	case opt_int_constraint_range:
2227141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Int *) value)
2228141cc406Sopenharmony_ci	    {
2229141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2230141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2231141cc406Sopenharmony_ci	      break;
2232141cc406Sopenharmony_ci	    }
2233141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Int *) value;
2234141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2235141cc406Sopenharmony_ci	       option, test_device->opt[option].name, *(SANE_Int *) value);
2236141cc406Sopenharmony_ci	  break;
2237141cc406Sopenharmony_ci	case opt_int_inexact:
2238141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Int *) value)
2239141cc406Sopenharmony_ci	    {
2240141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2241141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2242141cc406Sopenharmony_ci	      break;
2243141cc406Sopenharmony_ci	    }
2244141cc406Sopenharmony_ci          *(SANE_Int *) value += 1;
2245141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Int *) value;
2246141cc406Sopenharmony_ci          myinfo |= SANE_INFO_INEXACT;
2247141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2248141cc406Sopenharmony_ci	       option, test_device->opt[option].name, *(SANE_Int *) value);
2249141cc406Sopenharmony_ci	  break;
2250141cc406Sopenharmony_ci	case opt_fuzzy_parameters:	/* Bool with parameter reloading */
2251141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2252141cc406Sopenharmony_ci	    {
2253141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2254141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2255141cc406Sopenharmony_ci	      break;
2256141cc406Sopenharmony_ci	    }
2257141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2258141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2259141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2260141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2261141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2262141cc406Sopenharmony_ci	  break;
2263141cc406Sopenharmony_ci	case opt_invert_endianess:	/* Bool */
2264141cc406Sopenharmony_ci	case opt_non_blocking:
2265141cc406Sopenharmony_ci	case opt_select_fd:
2266141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect:
2267141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect_auto:
2268141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect_emulated:
2269141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2270141cc406Sopenharmony_ci	    {
2271141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2272141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2273141cc406Sopenharmony_ci	      break;
2274141cc406Sopenharmony_ci	    }
2275141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2276141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2277141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2278141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2279141cc406Sopenharmony_ci	  break;
2280141cc406Sopenharmony_ci	case opt_depth:	/* Word list with parameter and options reloading */
2281141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Int *) value)
2282141cc406Sopenharmony_ci	    {
2283141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2284141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2285141cc406Sopenharmony_ci	      break;
2286141cc406Sopenharmony_ci	    }
2287141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Int *) value;
2288141cc406Sopenharmony_ci	  if (test_device->val[option].w == 16)
2289141cc406Sopenharmony_ci	    test_device->opt[opt_invert_endianess].cap &= ~SANE_CAP_INACTIVE;
2290141cc406Sopenharmony_ci	  else
2291141cc406Sopenharmony_ci	    test_device->opt[opt_invert_endianess].cap |= SANE_CAP_INACTIVE;
2292141cc406Sopenharmony_ci
2293141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2294141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2295141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2296141cc406Sopenharmony_ci	       option, test_device->opt[option].name, *(SANE_Int *) value);
2297141cc406Sopenharmony_ci	  break;
2298141cc406Sopenharmony_ci	case opt_three_pass_order:	/* String list with parameter reload */
2299141cc406Sopenharmony_ci	  if (strcmp (test_device->val[option].s, value) == 0)
2300141cc406Sopenharmony_ci	    {
2301141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2302141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2303141cc406Sopenharmony_ci	      break;
2304141cc406Sopenharmony_ci	    }
2305141cc406Sopenharmony_ci	  strcpy (test_device->val[option].s, (SANE_String) value);
2306141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2307141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2308141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (SANE_String) value);
2309141cc406Sopenharmony_ci	  break;
2310141cc406Sopenharmony_ci	case opt_int_constraint_word_list:	/* Word list */
2311141cc406Sopenharmony_ci	case opt_fixed_constraint_word_list:
2312141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Int *) value)
2313141cc406Sopenharmony_ci	    {
2314141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2315141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2316141cc406Sopenharmony_ci	      break;
2317141cc406Sopenharmony_ci	    }
2318141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Int *) value;
2319141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %d\n",
2320141cc406Sopenharmony_ci	       option, test_device->opt[option].name, *(SANE_Int *) value);
2321141cc406Sopenharmony_ci	  break;
2322141cc406Sopenharmony_ci	case opt_read_status_code:	/* String (list) */
2323141cc406Sopenharmony_ci	case opt_test_picture:
2324141cc406Sopenharmony_ci	case opt_string:
2325141cc406Sopenharmony_ci	case opt_string_constraint_string_list:
2326141cc406Sopenharmony_ci	case opt_string_constraint_long_string_list:
2327141cc406Sopenharmony_ci	case opt_scan_source:
2328141cc406Sopenharmony_ci	  if (strcmp (test_device->val[option].s, value) == 0)
2329141cc406Sopenharmony_ci	    {
2330141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2331141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2332141cc406Sopenharmony_ci	      break;
2333141cc406Sopenharmony_ci	    }
2334141cc406Sopenharmony_ci	  strcpy (test_device->val[option].s, (SANE_String) value);
2335141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to `%s'\n",
2336141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (SANE_String) value);
2337141cc406Sopenharmony_ci	  break;
2338141cc406Sopenharmony_ci	case opt_int_array:	/* Word array */
2339141cc406Sopenharmony_ci	case opt_int_array_constraint_range:
2340141cc406Sopenharmony_ci	case opt_gamma_red:
2341141cc406Sopenharmony_ci	case opt_gamma_green:
2342141cc406Sopenharmony_ci	case opt_gamma_blue:
2343141cc406Sopenharmony_ci	case opt_gamma_all:
2344141cc406Sopenharmony_ci	case opt_int_array_constraint_word_list:
2345141cc406Sopenharmony_ci	  memcpy (test_device->val[option].wa, value,
2346141cc406Sopenharmony_ci		  (size_t) test_device->opt[option].size);
2347141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %p\n",
2348141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (void *) value);
2349141cc406Sopenharmony_ci	  if (option == opt_gamma_all) {
2350141cc406Sopenharmony_ci	      print_gamma_table(gamma_all, GAMMA_ALL_SIZE);
2351141cc406Sopenharmony_ci	  }
2352141cc406Sopenharmony_ci	  if (option == opt_gamma_red) {
2353141cc406Sopenharmony_ci	      print_gamma_table(gamma_red, GAMMA_RED_SIZE);
2354141cc406Sopenharmony_ci	  }
2355141cc406Sopenharmony_ci	  break;
2356141cc406Sopenharmony_ci	  /* options with side-effects */
2357141cc406Sopenharmony_ci	case opt_print_options:
2358141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s)\n",
2359141cc406Sopenharmony_ci	       option, test_device->opt[option].name);
2360141cc406Sopenharmony_ci	  print_options (test_device);
2361141cc406Sopenharmony_ci	  break;
2362141cc406Sopenharmony_ci	case opt_button:
2363141cc406Sopenharmony_ci	  DBG (0, "Yes! You pressed me!\n");
2364141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s)\n",
2365141cc406Sopenharmony_ci	       option, test_device->opt[option].name);
2366141cc406Sopenharmony_ci	  break;
2367141cc406Sopenharmony_ci	case opt_mode:
2368141cc406Sopenharmony_ci	  if (strcmp (test_device->val[option].s, value) == 0)
2369141cc406Sopenharmony_ci	    {
2370141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2371141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2372141cc406Sopenharmony_ci	      break;
2373141cc406Sopenharmony_ci	    }
2374141cc406Sopenharmony_ci	  strcpy (test_device->val[option].s, (SANE_String) value);
2375141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2376141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2377141cc406Sopenharmony_ci	  if (strcmp (test_device->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
2378141cc406Sopenharmony_ci	    {
2379141cc406Sopenharmony_ci	      test_device->opt[opt_three_pass].cap &= ~SANE_CAP_INACTIVE;
2380141cc406Sopenharmony_ci	      if (test_device->val[opt_three_pass].w == SANE_TRUE)
2381141cc406Sopenharmony_ci		test_device->opt[opt_three_pass_order].cap
2382141cc406Sopenharmony_ci		  &= ~SANE_CAP_INACTIVE;
2383141cc406Sopenharmony_ci	    }
2384141cc406Sopenharmony_ci	  else
2385141cc406Sopenharmony_ci	    {
2386141cc406Sopenharmony_ci	      test_device->opt[opt_three_pass].cap |= SANE_CAP_INACTIVE;
2387141cc406Sopenharmony_ci	      test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE;
2388141cc406Sopenharmony_ci	    }
2389141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2390141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (SANE_String) value);
2391141cc406Sopenharmony_ci	  break;
2392141cc406Sopenharmony_ci	case opt_three_pass:
2393141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2394141cc406Sopenharmony_ci	    {
2395141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2396141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2397141cc406Sopenharmony_ci	      break;
2398141cc406Sopenharmony_ci	    }
2399141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2400141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2401141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2402141cc406Sopenharmony_ci	  if (test_device->val[option].w == SANE_TRUE)
2403141cc406Sopenharmony_ci	    test_device->opt[opt_three_pass_order].cap &= ~SANE_CAP_INACTIVE;
2404141cc406Sopenharmony_ci	  else
2405141cc406Sopenharmony_ci	    test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE;
2406141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2407141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2408141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2409141cc406Sopenharmony_ci	  break;
2410141cc406Sopenharmony_ci	case opt_hand_scanner:
2411141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2412141cc406Sopenharmony_ci	    {
2413141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2414141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2415141cc406Sopenharmony_ci	      break;
2416141cc406Sopenharmony_ci	    }
2417141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2418141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
2419141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2420141cc406Sopenharmony_ci	  if (test_device->val[option].w == SANE_TRUE)
2421141cc406Sopenharmony_ci	    {
2422141cc406Sopenharmony_ci	      test_device->opt[opt_tl_x].cap |= SANE_CAP_INACTIVE;
2423141cc406Sopenharmony_ci	      test_device->opt[opt_tl_y].cap |= SANE_CAP_INACTIVE;
2424141cc406Sopenharmony_ci	      test_device->opt[opt_br_x].cap |= SANE_CAP_INACTIVE;
2425141cc406Sopenharmony_ci	      test_device->opt[opt_br_y].cap |= SANE_CAP_INACTIVE;
2426141cc406Sopenharmony_ci	    }
2427141cc406Sopenharmony_ci	  else
2428141cc406Sopenharmony_ci	    {
2429141cc406Sopenharmony_ci	      test_device->opt[opt_tl_x].cap &= ~SANE_CAP_INACTIVE;
2430141cc406Sopenharmony_ci	      test_device->opt[opt_tl_y].cap &= ~SANE_CAP_INACTIVE;
2431141cc406Sopenharmony_ci	      test_device->opt[opt_br_x].cap &= ~SANE_CAP_INACTIVE;
2432141cc406Sopenharmony_ci	      test_device->opt[opt_br_y].cap &= ~SANE_CAP_INACTIVE;
2433141cc406Sopenharmony_ci	    }
2434141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2435141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2436141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2437141cc406Sopenharmony_ci	  break;
2438141cc406Sopenharmony_ci	case opt_read_limit:
2439141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2440141cc406Sopenharmony_ci	    {
2441141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2442141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2443141cc406Sopenharmony_ci	      break;
2444141cc406Sopenharmony_ci	    }
2445141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2446141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2447141cc406Sopenharmony_ci	  if (test_device->val[option].w == SANE_TRUE)
2448141cc406Sopenharmony_ci	    test_device->opt[opt_read_limit_size].cap &= ~SANE_CAP_INACTIVE;
2449141cc406Sopenharmony_ci	  else
2450141cc406Sopenharmony_ci	    test_device->opt[opt_read_limit_size].cap |= SANE_CAP_INACTIVE;
2451141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2452141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2453141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2454141cc406Sopenharmony_ci	  break;
2455141cc406Sopenharmony_ci	case opt_read_delay:
2456141cc406Sopenharmony_ci	  if (test_device->val[option].w == *(SANE_Bool *) value)
2457141cc406Sopenharmony_ci	    {
2458141cc406Sopenharmony_ci	      DBG (4, "sane_control_option: option %d (%s) not changed\n",
2459141cc406Sopenharmony_ci		   option, test_device->opt[option].name);
2460141cc406Sopenharmony_ci	      break;
2461141cc406Sopenharmony_ci	    }
2462141cc406Sopenharmony_ci	  test_device->val[option].w = *(SANE_Bool *) value;
2463141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
2464141cc406Sopenharmony_ci	  if (test_device->val[option].w == SANE_TRUE)
2465141cc406Sopenharmony_ci	    test_device->opt[opt_read_delay_duration].cap
2466141cc406Sopenharmony_ci	      &= ~SANE_CAP_INACTIVE;
2467141cc406Sopenharmony_ci	  else
2468141cc406Sopenharmony_ci	    test_device->opt[opt_read_delay_duration].cap |=
2469141cc406Sopenharmony_ci	      SANE_CAP_INACTIVE;
2470141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: set option %d (%s) to %s\n", option,
2471141cc406Sopenharmony_ci	       test_device->opt[option].name,
2472141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2473141cc406Sopenharmony_ci	  break;
2474141cc406Sopenharmony_ci	case opt_enable_test_options:
2475141cc406Sopenharmony_ci	  {
2476141cc406Sopenharmony_ci	    int option_number;
2477141cc406Sopenharmony_ci	    if (test_device->val[option].w == *(SANE_Bool *) value)
2478141cc406Sopenharmony_ci	      {
2479141cc406Sopenharmony_ci		DBG (4, "sane_control_option: option %d (%s) not changed\n",
2480141cc406Sopenharmony_ci		     option, test_device->opt[option].name);
2481141cc406Sopenharmony_ci		break;
2482141cc406Sopenharmony_ci	      }
2483141cc406Sopenharmony_ci	    test_device->val[option].w = *(SANE_Bool *) value;
2484141cc406Sopenharmony_ci	    myinfo |= SANE_INFO_RELOAD_OPTIONS;
2485141cc406Sopenharmony_ci	    for (option_number = opt_bool_soft_select_soft_detect;
2486141cc406Sopenharmony_ci		 option_number < num_options; option_number++)
2487141cc406Sopenharmony_ci	      {
2488141cc406Sopenharmony_ci		if (test_device->opt[option_number].type == SANE_TYPE_GROUP)
2489141cc406Sopenharmony_ci		  continue;
2490141cc406Sopenharmony_ci		if (test_device->val[option].w == SANE_TRUE)
2491141cc406Sopenharmony_ci		  test_device->opt[option_number].cap &= ~SANE_CAP_INACTIVE;
2492141cc406Sopenharmony_ci		else
2493141cc406Sopenharmony_ci		  test_device->opt[option_number].cap |= SANE_CAP_INACTIVE;
2494141cc406Sopenharmony_ci	      }
2495141cc406Sopenharmony_ci	    DBG (4, "sane_control_option: set option %d (%s) to %s\n",
2496141cc406Sopenharmony_ci		 option, test_device->opt[option].name,
2497141cc406Sopenharmony_ci		 *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2498141cc406Sopenharmony_ci	    break;
2499141cc406Sopenharmony_ci	  }
2500141cc406Sopenharmony_ci	default:
2501141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: trying to set unexpected option\n");
2502141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2503141cc406Sopenharmony_ci	}
2504141cc406Sopenharmony_ci      break;
2505141cc406Sopenharmony_ci
2506141cc406Sopenharmony_ci    case SANE_ACTION_GET_VALUE:
2507141cc406Sopenharmony_ci      switch (option)
2508141cc406Sopenharmony_ci	{
2509141cc406Sopenharmony_ci	case opt_num_opts:
2510141cc406Sopenharmony_ci	  *(SANE_Word *) value = num_options;
2511141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: get option 0, value = %d\n",
2512141cc406Sopenharmony_ci	       num_options);
2513141cc406Sopenharmony_ci	  break;
2514141cc406Sopenharmony_ci	case opt_tl_x:		/* Fixed options */
2515141cc406Sopenharmony_ci	case opt_tl_y:
2516141cc406Sopenharmony_ci	case opt_br_x:
2517141cc406Sopenharmony_ci	case opt_br_y:
2518141cc406Sopenharmony_ci	case opt_resolution:
2519141cc406Sopenharmony_ci	case opt_fixed:
2520141cc406Sopenharmony_ci	case opt_fixed_constraint_range:
2521141cc406Sopenharmony_ci	case opt_fixed_constraint_word_list:
2522141cc406Sopenharmony_ci	  {
2523141cc406Sopenharmony_ci	    *(SANE_Fixed *) value = test_device->val[option].w;
2524141cc406Sopenharmony_ci	    DBG (4,
2525141cc406Sopenharmony_ci		 "sane_control_option: get option %d (%s), value=%.1f %s\n",
2526141cc406Sopenharmony_ci		 option, test_device->opt[option].name,
2527141cc406Sopenharmony_ci		 SANE_UNFIX (*(SANE_Fixed *) value),
2528141cc406Sopenharmony_ci		 test_device->opt[option].unit ==
2529141cc406Sopenharmony_ci		 SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : "");
2530141cc406Sopenharmony_ci	    break;
2531141cc406Sopenharmony_ci	  }
2532141cc406Sopenharmony_ci	case opt_hand_scanner:	/* Bool options */
2533141cc406Sopenharmony_ci	case opt_three_pass:
2534141cc406Sopenharmony_ci	case opt_invert_endianess:
2535141cc406Sopenharmony_ci	case opt_read_limit:
2536141cc406Sopenharmony_ci	case opt_read_delay:
2537141cc406Sopenharmony_ci	case opt_fuzzy_parameters:
2538141cc406Sopenharmony_ci	case opt_non_blocking:
2539141cc406Sopenharmony_ci	case opt_select_fd:
2540141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect:
2541141cc406Sopenharmony_ci	case opt_bool_hard_select_soft_detect:
2542141cc406Sopenharmony_ci	case opt_bool_soft_detect:
2543141cc406Sopenharmony_ci	case opt_enable_test_options:
2544141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect_emulated:
2545141cc406Sopenharmony_ci	case opt_bool_soft_select_soft_detect_auto:
2546141cc406Sopenharmony_ci	  *(SANE_Bool *) value = test_device->val[option].w;
2547141cc406Sopenharmony_ci	  DBG (4,
2548141cc406Sopenharmony_ci	       "sane_control_option: get option %d (%s), value=%s\n",
2549141cc406Sopenharmony_ci	       option, test_device->opt[option].name,
2550141cc406Sopenharmony_ci	       *(SANE_Bool *) value == SANE_TRUE ? "true" : "false");
2551141cc406Sopenharmony_ci	  break;
2552141cc406Sopenharmony_ci	case opt_mode:		/* String (list) options */
2553141cc406Sopenharmony_ci	case opt_three_pass_order:
2554141cc406Sopenharmony_ci	case opt_read_status_code:
2555141cc406Sopenharmony_ci	case opt_test_picture:
2556141cc406Sopenharmony_ci	case opt_string:
2557141cc406Sopenharmony_ci	case opt_string_constraint_string_list:
2558141cc406Sopenharmony_ci	case opt_string_constraint_long_string_list:
2559141cc406Sopenharmony_ci	case opt_scan_source:
2560141cc406Sopenharmony_ci	  strcpy (value, test_device->val[option].s);
2561141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n",
2562141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (SANE_String) value);
2563141cc406Sopenharmony_ci	  break;
2564141cc406Sopenharmony_ci	case opt_depth:	/* Int + word list options */
2565141cc406Sopenharmony_ci	case opt_read_limit_size:
2566141cc406Sopenharmony_ci	case opt_ppl_loss:
2567141cc406Sopenharmony_ci	case opt_read_delay_duration:
2568141cc406Sopenharmony_ci	case opt_int:
2569141cc406Sopenharmony_ci        case opt_int_inexact:
2570141cc406Sopenharmony_ci	case opt_int_constraint_range:
2571141cc406Sopenharmony_ci	case opt_int_constraint_word_list:
2572141cc406Sopenharmony_ci	  *(SANE_Int *) value = test_device->val[option].w;
2573141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: get option %d (%s), value=%d\n",
2574141cc406Sopenharmony_ci	       option, test_device->opt[option].name, *(SANE_Int *) value);
2575141cc406Sopenharmony_ci	  break;
2576141cc406Sopenharmony_ci	case opt_int_array:	/* Int array */
2577141cc406Sopenharmony_ci	case opt_int_array_constraint_range:
2578141cc406Sopenharmony_ci	case opt_gamma_red:
2579141cc406Sopenharmony_ci	case opt_gamma_green:
2580141cc406Sopenharmony_ci	case opt_gamma_blue:
2581141cc406Sopenharmony_ci	case opt_gamma_all:
2582141cc406Sopenharmony_ci	case opt_int_array_constraint_word_list:
2583141cc406Sopenharmony_ci	  memcpy (value, test_device->val[option].wa,
2584141cc406Sopenharmony_ci		  (size_t) test_device->opt[option].size);
2585141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: get option %d (%s), value=%p\n",
2586141cc406Sopenharmony_ci	       option, test_device->opt[option].name, (void *) value);
2587141cc406Sopenharmony_ci	  break;
2588141cc406Sopenharmony_ci	default:
2589141cc406Sopenharmony_ci	  DBG (1, "sane_control_option: trying to get unexpected option\n");
2590141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
2591141cc406Sopenharmony_ci	}
2592141cc406Sopenharmony_ci      break;
2593141cc406Sopenharmony_ci    default:
2594141cc406Sopenharmony_ci      DBG (1, "sane_control_option: trying unexpected action %d\n", action);
2595141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2596141cc406Sopenharmony_ci    }
2597141cc406Sopenharmony_ci
2598141cc406Sopenharmony_ci  if (info)
2599141cc406Sopenharmony_ci    *info = myinfo;
2600141cc406Sopenharmony_ci
2601141cc406Sopenharmony_ci  if(myinfo & SANE_INFO_RELOAD_OPTIONS){
2602141cc406Sopenharmony_ci    SANE_Int i = 0;
2603141cc406Sopenharmony_ci    for(i=1;i<num_options;i++){
2604141cc406Sopenharmony_ci      test_device->loaded[i] = 0;
2605141cc406Sopenharmony_ci    }
2606141cc406Sopenharmony_ci  }
2607141cc406Sopenharmony_ci
2608141cc406Sopenharmony_ci  DBG (4, "sane_control_option: finished, info=%s %s %s \n",
2609141cc406Sopenharmony_ci       myinfo & SANE_INFO_INEXACT ? "inexact" : "",
2610141cc406Sopenharmony_ci       myinfo & SANE_INFO_RELOAD_PARAMS ? "reload_parameters" : "",
2611141cc406Sopenharmony_ci       myinfo & SANE_INFO_RELOAD_OPTIONS ? "reload_options" : "");
2612141cc406Sopenharmony_ci
2613141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2614141cc406Sopenharmony_ci}
2615141cc406Sopenharmony_ci
2616141cc406Sopenharmony_ci
2617141cc406Sopenharmony_ciSANE_Status
2618141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2619141cc406Sopenharmony_ci{
2620141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2621141cc406Sopenharmony_ci  SANE_Parameters *p;
2622141cc406Sopenharmony_ci  double res, tl_x = 0, tl_y = 0, br_x = 0, br_y = 0;
2623141cc406Sopenharmony_ci  SANE_String text_format, mode;
2624141cc406Sopenharmony_ci  SANE_Int channels = 1;
2625141cc406Sopenharmony_ci
2626141cc406Sopenharmony_ci  DBG (2, "sane_get_parameters: handle=%p, params=%p\n",
2627141cc406Sopenharmony_ci       (void *) handle, (void *) params);
2628141cc406Sopenharmony_ci  if (!inited)
2629141cc406Sopenharmony_ci    {
2630141cc406Sopenharmony_ci      DBG (1, "sane_get_parameters: not inited, call sane_init() first\n");
2631141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2632141cc406Sopenharmony_ci    }
2633141cc406Sopenharmony_ci  if (!check_handle (handle))
2634141cc406Sopenharmony_ci    {
2635141cc406Sopenharmony_ci      DBG (1, "sane_get_parameters: handle %p unknown\n", (void *) handle);
2636141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2637141cc406Sopenharmony_ci    }
2638141cc406Sopenharmony_ci  if (!test_device->open)
2639141cc406Sopenharmony_ci    {
2640141cc406Sopenharmony_ci      DBG (1, "sane_get_parameters: handle %p not open\n", (void *) handle);
2641141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2642141cc406Sopenharmony_ci    }
2643141cc406Sopenharmony_ci
2644141cc406Sopenharmony_ci  res = SANE_UNFIX (test_device->val[opt_resolution].w);
2645141cc406Sopenharmony_ci  mode = test_device->val[opt_mode].s;
2646141cc406Sopenharmony_ci  p = &test_device->params;
2647141cc406Sopenharmony_ci  p->depth = test_device->val[opt_depth].w;
2648141cc406Sopenharmony_ci
2649141cc406Sopenharmony_ci  if (test_device->val[opt_hand_scanner].w == SANE_TRUE)
2650141cc406Sopenharmony_ci    {
2651141cc406Sopenharmony_ci      tl_x = 0.0;
2652141cc406Sopenharmony_ci      br_x = 110.0;
2653141cc406Sopenharmony_ci      tl_y = 0.0;
2654141cc406Sopenharmony_ci      br_y = 170.0;
2655141cc406Sopenharmony_ci      p->lines = -1;
2656141cc406Sopenharmony_ci      test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH);
2657141cc406Sopenharmony_ci    }
2658141cc406Sopenharmony_ci  else
2659141cc406Sopenharmony_ci    {
2660141cc406Sopenharmony_ci      tl_x = SANE_UNFIX (test_device->val[opt_tl_x].w);
2661141cc406Sopenharmony_ci      tl_y = SANE_UNFIX (test_device->val[opt_tl_y].w);
2662141cc406Sopenharmony_ci      br_x = SANE_UNFIX (test_device->val[opt_br_x].w);
2663141cc406Sopenharmony_ci      br_y = SANE_UNFIX (test_device->val[opt_br_y].w);
2664141cc406Sopenharmony_ci      if (tl_x > br_x)
2665141cc406Sopenharmony_ci	swap_double (&tl_x, &br_x);
2666141cc406Sopenharmony_ci      if (tl_y > br_y)
2667141cc406Sopenharmony_ci	swap_double (&tl_y, &br_y);
2668141cc406Sopenharmony_ci      test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH);
2669141cc406Sopenharmony_ci      if (test_device->lines < 1)
2670141cc406Sopenharmony_ci	test_device->lines = 1;
2671141cc406Sopenharmony_ci      p->lines = test_device->lines;
2672141cc406Sopenharmony_ci      if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE
2673141cc406Sopenharmony_ci	  && test_device->scanning == SANE_FALSE)
2674141cc406Sopenharmony_ci	p->lines *= (SANE_Int) random_factor;
2675141cc406Sopenharmony_ci    }
2676141cc406Sopenharmony_ci
2677141cc406Sopenharmony_ci  if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
2678141cc406Sopenharmony_ci    {
2679141cc406Sopenharmony_ci      p->format = SANE_FRAME_GRAY;
2680141cc406Sopenharmony_ci      p->last_frame = SANE_TRUE;
2681141cc406Sopenharmony_ci    }
2682141cc406Sopenharmony_ci  else				/* Color */
2683141cc406Sopenharmony_ci    {
2684141cc406Sopenharmony_ci      if (test_device->val[opt_three_pass].w == SANE_TRUE)
2685141cc406Sopenharmony_ci	{
2686141cc406Sopenharmony_ci	  if (test_device->val[opt_three_pass_order].s[test_device->pass]
2687141cc406Sopenharmony_ci	      == 'R')
2688141cc406Sopenharmony_ci	    p->format = SANE_FRAME_RED;
2689141cc406Sopenharmony_ci	  else if (test_device->val[opt_three_pass_order].s[test_device->pass]
2690141cc406Sopenharmony_ci		   == 'G')
2691141cc406Sopenharmony_ci	    p->format = SANE_FRAME_GREEN;
2692141cc406Sopenharmony_ci	  else
2693141cc406Sopenharmony_ci	    p->format = SANE_FRAME_BLUE;
2694141cc406Sopenharmony_ci	  if (test_device->pass > 1)
2695141cc406Sopenharmony_ci	    p->last_frame = SANE_TRUE;
2696141cc406Sopenharmony_ci	  else
2697141cc406Sopenharmony_ci	    p->last_frame = SANE_FALSE;
2698141cc406Sopenharmony_ci	}
2699141cc406Sopenharmony_ci      else
2700141cc406Sopenharmony_ci	{
2701141cc406Sopenharmony_ci	  p->format = SANE_FRAME_RGB;
2702141cc406Sopenharmony_ci	  p->last_frame = SANE_TRUE;
2703141cc406Sopenharmony_ci	}
2704141cc406Sopenharmony_ci    }
2705141cc406Sopenharmony_ci
2706141cc406Sopenharmony_ci  p->pixels_per_line = (SANE_Int) (res * (br_x - tl_x) / MM_PER_INCH);
2707141cc406Sopenharmony_ci  if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE
2708141cc406Sopenharmony_ci      && test_device->scanning == SANE_FALSE)
2709141cc406Sopenharmony_ci    p->pixels_per_line *= (SANE_Int) random_factor;
2710141cc406Sopenharmony_ci  if (p->pixels_per_line < 1)
2711141cc406Sopenharmony_ci    p->pixels_per_line = 1;
2712141cc406Sopenharmony_ci
2713141cc406Sopenharmony_ci  if (p->format == SANE_FRAME_RGB)
2714141cc406Sopenharmony_ci    channels = 3;
2715141cc406Sopenharmony_ci
2716141cc406Sopenharmony_ci  if (p->depth == 1)
2717141cc406Sopenharmony_ci    p->bytes_per_line = channels * (int) ((p->pixels_per_line + 7) / 8);
2718141cc406Sopenharmony_ci  else				/* depth == 8 || depth == 16 */
2719141cc406Sopenharmony_ci    p->bytes_per_line = channels * p->pixels_per_line * ((p->depth + 7) / 8);
2720141cc406Sopenharmony_ci
2721141cc406Sopenharmony_ci  test_device->bytes_per_line = p->bytes_per_line;
2722141cc406Sopenharmony_ci
2723141cc406Sopenharmony_ci  p->pixels_per_line -= test_device->val[opt_ppl_loss].w;
2724141cc406Sopenharmony_ci  if (p->pixels_per_line < 1)
2725141cc406Sopenharmony_ci    p->pixels_per_line = 1;
2726141cc406Sopenharmony_ci  test_device->pixels_per_line = p->pixels_per_line;
2727141cc406Sopenharmony_ci
2728141cc406Sopenharmony_ci  switch (p->format)
2729141cc406Sopenharmony_ci    {
2730141cc406Sopenharmony_ci    case SANE_FRAME_GRAY:
2731141cc406Sopenharmony_ci      text_format = "gray";
2732141cc406Sopenharmony_ci      break;
2733141cc406Sopenharmony_ci    case SANE_FRAME_RGB:
2734141cc406Sopenharmony_ci      text_format = "rgb";
2735141cc406Sopenharmony_ci      break;
2736141cc406Sopenharmony_ci    case SANE_FRAME_RED:
2737141cc406Sopenharmony_ci      text_format = "red";
2738141cc406Sopenharmony_ci      break;
2739141cc406Sopenharmony_ci    case SANE_FRAME_GREEN:
2740141cc406Sopenharmony_ci      text_format = "green";
2741141cc406Sopenharmony_ci      break;
2742141cc406Sopenharmony_ci    case SANE_FRAME_BLUE:
2743141cc406Sopenharmony_ci      text_format = "blue";
2744141cc406Sopenharmony_ci      break;
2745141cc406Sopenharmony_ci    default:
2746141cc406Sopenharmony_ci      text_format = "unknown";
2747141cc406Sopenharmony_ci      break;
2748141cc406Sopenharmony_ci    }
2749141cc406Sopenharmony_ci
2750141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: format=%s\n", text_format);
2751141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: last_frame=%s\n",
2752141cc406Sopenharmony_ci       p->last_frame ? "true" : "false");
2753141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: lines=%d\n", p->lines);
2754141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: depth=%d\n", p->depth);
2755141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: pixels_per_line=%d\n", p->pixels_per_line);
2756141cc406Sopenharmony_ci  DBG (3, "sane_get_parameters: bytes_per_line=%d\n", p->bytes_per_line);
2757141cc406Sopenharmony_ci
2758141cc406Sopenharmony_ci  if (params)
2759141cc406Sopenharmony_ci    *params = *p;
2760141cc406Sopenharmony_ci
2761141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2762141cc406Sopenharmony_ci}
2763141cc406Sopenharmony_ci
2764141cc406Sopenharmony_ciSANE_Status
2765141cc406Sopenharmony_cisane_start (SANE_Handle handle)
2766141cc406Sopenharmony_ci{
2767141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2768141cc406Sopenharmony_ci  int pipe_descriptor[2];
2769141cc406Sopenharmony_ci
2770141cc406Sopenharmony_ci  DBG (2, "sane_start: handle=%p\n", handle);
2771141cc406Sopenharmony_ci  if (!inited)
2772141cc406Sopenharmony_ci    {
2773141cc406Sopenharmony_ci      DBG (1, "sane_start: not inited, call sane_init() first\n");
2774141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2775141cc406Sopenharmony_ci    }
2776141cc406Sopenharmony_ci  if (!check_handle (handle))
2777141cc406Sopenharmony_ci    {
2778141cc406Sopenharmony_ci      DBG (1, "sane_start: handle %p unknown\n", handle);
2779141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2780141cc406Sopenharmony_ci    }
2781141cc406Sopenharmony_ci  if (!test_device->open)
2782141cc406Sopenharmony_ci    {
2783141cc406Sopenharmony_ci      DBG (1, "sane_start: not open\n");
2784141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2785141cc406Sopenharmony_ci    }
2786141cc406Sopenharmony_ci  if (test_device->scanning
2787141cc406Sopenharmony_ci      && (test_device->val[opt_three_pass].w == SANE_FALSE
2788141cc406Sopenharmony_ci	  && strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0))
2789141cc406Sopenharmony_ci    {
2790141cc406Sopenharmony_ci      DBG (1, "sane_start: already scanning\n");
2791141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2792141cc406Sopenharmony_ci    }
2793141cc406Sopenharmony_ci  if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0
2794141cc406Sopenharmony_ci      && test_device->val[opt_three_pass].w == SANE_TRUE
2795141cc406Sopenharmony_ci      && test_device->pass > 2)
2796141cc406Sopenharmony_ci    {
2797141cc406Sopenharmony_ci      DBG (1, "sane_start: already in last pass of three\n");
2798141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2799141cc406Sopenharmony_ci    }
2800141cc406Sopenharmony_ci
2801141cc406Sopenharmony_ci  if (test_device->pass == 0)
2802141cc406Sopenharmony_ci    {
2803141cc406Sopenharmony_ci      test_device->number_of_scans++;
2804141cc406Sopenharmony_ci      DBG (3, "sane_start: scanning page %d\n", test_device->number_of_scans);
2805141cc406Sopenharmony_ci
2806141cc406Sopenharmony_ci      if ((strcmp (test_device->val[opt_scan_source].s, "Automatic Document Feeder") == 0) &&
2807141cc406Sopenharmony_ci	  (((test_device->number_of_scans) % 11) == 0))
2808141cc406Sopenharmony_ci	{
2809141cc406Sopenharmony_ci	  DBG (1, "sane_start: Document feeder is out of documents!\n");
2810141cc406Sopenharmony_ci	  return SANE_STATUS_NO_DOCS;
2811141cc406Sopenharmony_ci	}
2812141cc406Sopenharmony_ci    }
2813141cc406Sopenharmony_ci
2814141cc406Sopenharmony_ci  test_device->scanning = SANE_TRUE;
2815141cc406Sopenharmony_ci  test_device->cancelled = SANE_FALSE;
2816141cc406Sopenharmony_ci  test_device->eof = SANE_FALSE;
2817141cc406Sopenharmony_ci  test_device->bytes_total = 0;
2818141cc406Sopenharmony_ci
2819141cc406Sopenharmony_ci  sane_get_parameters (handle, 0);
2820141cc406Sopenharmony_ci
2821141cc406Sopenharmony_ci  if (test_device->params.lines == 0)
2822141cc406Sopenharmony_ci    {
2823141cc406Sopenharmony_ci      DBG (1, "sane_start: lines == 0\n");
2824141cc406Sopenharmony_ci      test_device->scanning = SANE_FALSE;
2825141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2826141cc406Sopenharmony_ci    }
2827141cc406Sopenharmony_ci  if (test_device->params.pixels_per_line == 0)
2828141cc406Sopenharmony_ci    {
2829141cc406Sopenharmony_ci      DBG (1, "sane_start: pixels_per_line == 0\n");
2830141cc406Sopenharmony_ci      test_device->scanning = SANE_FALSE;
2831141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2832141cc406Sopenharmony_ci    }
2833141cc406Sopenharmony_ci  if (test_device->params.bytes_per_line == 0)
2834141cc406Sopenharmony_ci    {
2835141cc406Sopenharmony_ci      DBG (1, "sane_start: bytes_per_line == 0\n");
2836141cc406Sopenharmony_ci      test_device->scanning = SANE_FALSE;
2837141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2838141cc406Sopenharmony_ci    }
2839141cc406Sopenharmony_ci
2840141cc406Sopenharmony_ci  if (pipe (pipe_descriptor) < 0)
2841141cc406Sopenharmony_ci    {
2842141cc406Sopenharmony_ci      DBG (1, "sane_start: pipe failed (%s)\n", strerror (errno));
2843141cc406Sopenharmony_ci      return SANE_STATUS_IO_ERROR;
2844141cc406Sopenharmony_ci    }
2845141cc406Sopenharmony_ci
2846141cc406Sopenharmony_ci  /* create reader routine as new process or thread */
2847141cc406Sopenharmony_ci  test_device->pipe = pipe_descriptor[0];
2848141cc406Sopenharmony_ci  test_device->reader_fds = pipe_descriptor[1];
2849141cc406Sopenharmony_ci  test_device->reader_pid =
2850141cc406Sopenharmony_ci    sanei_thread_begin (reader_task, (void *) test_device);
2851141cc406Sopenharmony_ci
2852141cc406Sopenharmony_ci  if (!sanei_thread_is_valid (test_device->reader_pid))
2853141cc406Sopenharmony_ci    {
2854141cc406Sopenharmony_ci      DBG (1, "sane_start: sanei_thread_begin failed (%s)\n",
2855141cc406Sopenharmony_ci	   strerror (errno));
2856141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
2857141cc406Sopenharmony_ci    }
2858141cc406Sopenharmony_ci
2859141cc406Sopenharmony_ci  if (sanei_thread_is_forked ())
2860141cc406Sopenharmony_ci    {
2861141cc406Sopenharmony_ci      close (test_device->reader_fds);
2862141cc406Sopenharmony_ci      test_device->reader_fds = -1;
2863141cc406Sopenharmony_ci    }
2864141cc406Sopenharmony_ci
2865141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2866141cc406Sopenharmony_ci}
2867141cc406Sopenharmony_ci
2868141cc406Sopenharmony_ci
2869141cc406Sopenharmony_ciSANE_Status
2870141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data,
2871141cc406Sopenharmony_ci	   SANE_Int max_length, SANE_Int * length)
2872141cc406Sopenharmony_ci{
2873141cc406Sopenharmony_ci  Test_Device *test_device = handle;
2874141cc406Sopenharmony_ci  SANE_Int max_scan_length;
2875141cc406Sopenharmony_ci  ssize_t bytes_read;
2876141cc406Sopenharmony_ci  size_t read_count;
2877141cc406Sopenharmony_ci  size_t bytes_total = (size_t) test_device->lines * (size_t) test_device->bytes_per_line;
2878141cc406Sopenharmony_ci
2879141cc406Sopenharmony_ci
2880141cc406Sopenharmony_ci  DBG (4, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n",
2881141cc406Sopenharmony_ci       handle, (void *) data, max_length, (void *) length);
2882141cc406Sopenharmony_ci  if (!inited)
2883141cc406Sopenharmony_ci    {
2884141cc406Sopenharmony_ci      DBG (1, "sane_read: not inited, call sane_init() first\n");
2885141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2886141cc406Sopenharmony_ci    }
2887141cc406Sopenharmony_ci  if (!check_handle (handle))
2888141cc406Sopenharmony_ci    {
2889141cc406Sopenharmony_ci      DBG (1, "sane_read: handle %p unknown\n", handle);
2890141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2891141cc406Sopenharmony_ci    }
2892141cc406Sopenharmony_ci  if (!length)
2893141cc406Sopenharmony_ci    {
2894141cc406Sopenharmony_ci      DBG (1, "sane_read: length == NULL\n");
2895141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2896141cc406Sopenharmony_ci    }
2897141cc406Sopenharmony_ci
2898141cc406Sopenharmony_ci  if (strcmp (test_device->val[opt_read_status_code].s, "Default") != 0)
2899141cc406Sopenharmony_ci    {
2900141cc406Sopenharmony_ci      SANE_String_Const sc = test_device->val[opt_read_status_code].s;
2901141cc406Sopenharmony_ci      DBG (3, "sane_read: setting return status to %s\n", sc);
2902141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_UNSUPPORTED") == 0)
2903141cc406Sopenharmony_ci	return SANE_STATUS_UNSUPPORTED;
2904141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_CANCELLED") == 0)
2905141cc406Sopenharmony_ci	return SANE_STATUS_CANCELLED;
2906141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_DEVICE_BUSY") == 0)
2907141cc406Sopenharmony_ci	return SANE_STATUS_DEVICE_BUSY;
2908141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_INVAL") == 0)
2909141cc406Sopenharmony_ci	return SANE_STATUS_INVAL;
2910141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_EOF") == 0)
2911141cc406Sopenharmony_ci	return SANE_STATUS_EOF;
2912141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_JAMMED") == 0)
2913141cc406Sopenharmony_ci	return SANE_STATUS_JAMMED;
2914141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_NO_DOCS") == 0)
2915141cc406Sopenharmony_ci	return SANE_STATUS_NO_DOCS;
2916141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_COVER_OPEN") == 0)
2917141cc406Sopenharmony_ci	return SANE_STATUS_COVER_OPEN;
2918141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_IO_ERROR") == 0)
2919141cc406Sopenharmony_ci	return SANE_STATUS_IO_ERROR;
2920141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_NO_MEM") == 0)
2921141cc406Sopenharmony_ci	return SANE_STATUS_NO_MEM;
2922141cc406Sopenharmony_ci      if (strcmp (sc, "SANE_STATUS_ACCESS_DENIED") == 0)
2923141cc406Sopenharmony_ci	return SANE_STATUS_ACCESS_DENIED;
2924141cc406Sopenharmony_ci    }
2925141cc406Sopenharmony_ci
2926141cc406Sopenharmony_ci  max_scan_length = max_length;
2927141cc406Sopenharmony_ci  if (test_device->val[opt_read_limit].w == SANE_TRUE
2928141cc406Sopenharmony_ci      && test_device->val[opt_read_limit_size].w < max_scan_length)
2929141cc406Sopenharmony_ci    {
2930141cc406Sopenharmony_ci      max_scan_length = test_device->val[opt_read_limit_size].w;
2931141cc406Sopenharmony_ci      DBG (3, "sane_read: limiting max_scan_length to %d bytes\n",
2932141cc406Sopenharmony_ci	   max_scan_length);
2933141cc406Sopenharmony_ci    }
2934141cc406Sopenharmony_ci
2935141cc406Sopenharmony_ci  *length = 0;
2936141cc406Sopenharmony_ci
2937141cc406Sopenharmony_ci  if (!data)
2938141cc406Sopenharmony_ci    {
2939141cc406Sopenharmony_ci      DBG (1, "sane_read: data == NULL\n");
2940141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2941141cc406Sopenharmony_ci    }
2942141cc406Sopenharmony_ci  if (!test_device->open)
2943141cc406Sopenharmony_ci    {
2944141cc406Sopenharmony_ci      DBG (1, "sane_read: not open\n");
2945141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2946141cc406Sopenharmony_ci    }
2947141cc406Sopenharmony_ci  if (test_device->cancelled)
2948141cc406Sopenharmony_ci    {
2949141cc406Sopenharmony_ci      DBG (1, "sane_read: scan was cancelled\n");
2950141cc406Sopenharmony_ci      return SANE_STATUS_CANCELLED;
2951141cc406Sopenharmony_ci    }
2952141cc406Sopenharmony_ci  if (test_device->eof)
2953141cc406Sopenharmony_ci    {
2954141cc406Sopenharmony_ci      DBG (2, "sane_read: No more data available, sending EOF\n");
2955141cc406Sopenharmony_ci      return SANE_STATUS_EOF;
2956141cc406Sopenharmony_ci    }
2957141cc406Sopenharmony_ci  if (!test_device->scanning)
2958141cc406Sopenharmony_ci    {
2959141cc406Sopenharmony_ci      DBG (1, "sane_read: not scanning (call sane_start first)\n");
2960141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
2961141cc406Sopenharmony_ci    }
2962141cc406Sopenharmony_ci  read_count = (size_t) max_scan_length;
2963141cc406Sopenharmony_ci
2964141cc406Sopenharmony_ci  bytes_read = read (test_device->pipe, data, read_count);
2965141cc406Sopenharmony_ci  if (bytes_read == 0
2966141cc406Sopenharmony_ci      || ((size_t) bytes_read + (size_t) test_device->bytes_total >= bytes_total))
2967141cc406Sopenharmony_ci    {
2968141cc406Sopenharmony_ci      SANE_Status status;
2969141cc406Sopenharmony_ci      DBG (2, "sane_read: EOF reached\n");
2970141cc406Sopenharmony_ci      status = finish_pass (test_device);
2971141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2972141cc406Sopenharmony_ci	{
2973141cc406Sopenharmony_ci	  DBG (1, "sane_read: finish_pass returned `%s'\n",
2974141cc406Sopenharmony_ci	       sane_strstatus (status));
2975141cc406Sopenharmony_ci	  return status;
2976141cc406Sopenharmony_ci	}
2977141cc406Sopenharmony_ci      test_device->eof = SANE_TRUE;
2978141cc406Sopenharmony_ci      if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0
2979141cc406Sopenharmony_ci	  && test_device->val[opt_three_pass].w == SANE_TRUE)
2980141cc406Sopenharmony_ci	{
2981141cc406Sopenharmony_ci	  test_device->pass++;
2982141cc406Sopenharmony_ci	  if (test_device->pass > 2)
2983141cc406Sopenharmony_ci	    test_device->pass = 0;
2984141cc406Sopenharmony_ci	}
2985141cc406Sopenharmony_ci      if (bytes_read == 0)
2986141cc406Sopenharmony_ci	return SANE_STATUS_EOF;
2987141cc406Sopenharmony_ci    }
2988141cc406Sopenharmony_ci  else if (bytes_read < 0)
2989141cc406Sopenharmony_ci    {
2990141cc406Sopenharmony_ci      if (errno == EAGAIN)
2991141cc406Sopenharmony_ci	{
2992141cc406Sopenharmony_ci	  DBG (2, "sane_read: no data available, try again\n");
2993141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2994141cc406Sopenharmony_ci	}
2995141cc406Sopenharmony_ci      else
2996141cc406Sopenharmony_ci	{
2997141cc406Sopenharmony_ci	  DBG (1, "sane_read: read returned error: %s\n", strerror (errno));
2998141cc406Sopenharmony_ci	  return SANE_STATUS_IO_ERROR;
2999141cc406Sopenharmony_ci	}
3000141cc406Sopenharmony_ci    }
3001141cc406Sopenharmony_ci  *length = (SANE_Int) bytes_read;
3002141cc406Sopenharmony_ci  test_device->bytes_total += (size_t) bytes_read;
3003141cc406Sopenharmony_ci
3004141cc406Sopenharmony_ci  DBG (2, "sane_read: read %zu bytes of %zu, total %zu\n", (size_t) bytes_read,
3005141cc406Sopenharmony_ci       (size_t) max_scan_length, (size_t) test_device->bytes_total);
3006141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
3007141cc406Sopenharmony_ci}
3008141cc406Sopenharmony_ci
3009141cc406Sopenharmony_civoid
3010141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
3011141cc406Sopenharmony_ci{
3012141cc406Sopenharmony_ci  Test_Device *test_device = handle;
3013141cc406Sopenharmony_ci
3014141cc406Sopenharmony_ci  DBG (2, "sane_cancel: handle = %p\n", handle);
3015141cc406Sopenharmony_ci  if (!inited)
3016141cc406Sopenharmony_ci    {
3017141cc406Sopenharmony_ci      DBG (1, "sane_cancel: not inited, call sane_init() first\n");
3018141cc406Sopenharmony_ci      return;
3019141cc406Sopenharmony_ci    }
3020141cc406Sopenharmony_ci  if (!check_handle (handle))
3021141cc406Sopenharmony_ci    {
3022141cc406Sopenharmony_ci      DBG (1, "sane_cancel: handle %p unknown\n", handle);
3023141cc406Sopenharmony_ci      return;
3024141cc406Sopenharmony_ci    }
3025141cc406Sopenharmony_ci  if (!test_device->open)
3026141cc406Sopenharmony_ci    {
3027141cc406Sopenharmony_ci      DBG (1, "sane_cancel: not open\n");
3028141cc406Sopenharmony_ci      return;
3029141cc406Sopenharmony_ci    }
3030141cc406Sopenharmony_ci  if (test_device->cancelled)
3031141cc406Sopenharmony_ci    {
3032141cc406Sopenharmony_ci      DBG (1, "sane_cancel: scan already cancelled\n");
3033141cc406Sopenharmony_ci      return;
3034141cc406Sopenharmony_ci    }
3035141cc406Sopenharmony_ci  if (!test_device->scanning)
3036141cc406Sopenharmony_ci    {
3037141cc406Sopenharmony_ci      DBG (2, "sane_cancel: scan is already finished\n");
3038141cc406Sopenharmony_ci      return;
3039141cc406Sopenharmony_ci    }
3040141cc406Sopenharmony_ci  finish_pass (test_device);
3041141cc406Sopenharmony_ci  test_device->cancelled = SANE_TRUE;
3042141cc406Sopenharmony_ci  test_device->scanning = SANE_FALSE;
3043141cc406Sopenharmony_ci  test_device->eof = SANE_FALSE;
3044141cc406Sopenharmony_ci  test_device->pass = 0;
3045141cc406Sopenharmony_ci  return;
3046141cc406Sopenharmony_ci}
3047141cc406Sopenharmony_ci
3048141cc406Sopenharmony_ciSANE_Status
3049141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
3050141cc406Sopenharmony_ci{
3051141cc406Sopenharmony_ci  Test_Device *test_device = handle;
3052141cc406Sopenharmony_ci
3053141cc406Sopenharmony_ci  DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
3054141cc406Sopenharmony_ci       non_blocking);
3055141cc406Sopenharmony_ci  if (!inited)
3056141cc406Sopenharmony_ci    {
3057141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: not inited, call sane_init() first\n");
3058141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3059141cc406Sopenharmony_ci    }
3060141cc406Sopenharmony_ci  if (!check_handle (handle))
3061141cc406Sopenharmony_ci    {
3062141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: handle %p unknown\n", handle);
3063141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3064141cc406Sopenharmony_ci    }
3065141cc406Sopenharmony_ci  if (!test_device->open)
3066141cc406Sopenharmony_ci    {
3067141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: not open\n");
3068141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3069141cc406Sopenharmony_ci    }
3070141cc406Sopenharmony_ci  if (!test_device->scanning)
3071141cc406Sopenharmony_ci    {
3072141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: not scanning\n");
3073141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3074141cc406Sopenharmony_ci    }
3075141cc406Sopenharmony_ci  if (test_device->val[opt_non_blocking].w == SANE_TRUE)
3076141cc406Sopenharmony_ci    {
3077141cc406Sopenharmony_ci      if (fcntl (test_device->pipe,
3078141cc406Sopenharmony_ci		 F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
3079141cc406Sopenharmony_ci	{
3080141cc406Sopenharmony_ci	  DBG (1, "sane_set_io_mode: can't set io mode");
3081141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
3082141cc406Sopenharmony_ci	}
3083141cc406Sopenharmony_ci    }
3084141cc406Sopenharmony_ci  else
3085141cc406Sopenharmony_ci    {
3086141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: unsupported\n");
3087141cc406Sopenharmony_ci      if (non_blocking)
3088141cc406Sopenharmony_ci	return SANE_STATUS_UNSUPPORTED;
3089141cc406Sopenharmony_ci    }
3090141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
3091141cc406Sopenharmony_ci}
3092141cc406Sopenharmony_ci
3093141cc406Sopenharmony_ciSANE_Status
3094141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
3095141cc406Sopenharmony_ci{
3096141cc406Sopenharmony_ci  Test_Device *test_device = handle;
3097141cc406Sopenharmony_ci
3098141cc406Sopenharmony_ci  DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
3099141cc406Sopenharmony_ci       fd ? "!=" : "=");
3100141cc406Sopenharmony_ci  if (!inited)
3101141cc406Sopenharmony_ci    {
3102141cc406Sopenharmony_ci      DBG (1, "sane_get_select_fd: not inited, call sane_init() first\n");
3103141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3104141cc406Sopenharmony_ci    }
3105141cc406Sopenharmony_ci  if (!check_handle (handle))
3106141cc406Sopenharmony_ci    {
3107141cc406Sopenharmony_ci      DBG (1, "sane_get_select_fd: handle %p unknown\n", handle);
3108141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3109141cc406Sopenharmony_ci    }
3110141cc406Sopenharmony_ci  if (!test_device->open)
3111141cc406Sopenharmony_ci    {
3112141cc406Sopenharmony_ci      DBG (1, "sane_get_select_fd: not open\n");
3113141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3114141cc406Sopenharmony_ci    }
3115141cc406Sopenharmony_ci  if (!test_device->scanning)
3116141cc406Sopenharmony_ci    {
3117141cc406Sopenharmony_ci      DBG (1, "sane_get_select_fd: not scanning\n");
3118141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
3119141cc406Sopenharmony_ci    }
3120141cc406Sopenharmony_ci  if (test_device->val[opt_select_fd].w == SANE_TRUE)
3121141cc406Sopenharmony_ci    {
3122141cc406Sopenharmony_ci      *fd = test_device->pipe;
3123141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
3124141cc406Sopenharmony_ci    }
3125141cc406Sopenharmony_ci  DBG(1,"sane_get_select_fd: unsupported\n");
3126141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
3127141cc406Sopenharmony_ci}
3128