1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 1996, 1997 Andreas Beck
3141cc406Sopenharmony_ci   Copyright (C) 2000, 2001 Michael Herder <crapsite@gmx.net>
4141cc406Sopenharmony_ci   Copyright (C) 2001, 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
5141cc406Sopenharmony_ci   Copyright (C) 2008 Stéphane Voltz <stef.dev@free.fr>
6141cc406Sopenharmony_ci   This file is part of the SANE package.
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
9141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
10141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
11141cc406Sopenharmony_ci   License, or (at your option) any later version.
12141cc406Sopenharmony_ci
13141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
14141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
15141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16141cc406Sopenharmony_ci   General Public License for more details.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
19141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
22141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
23141cc406Sopenharmony_ci
24141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
25141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
26141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
27141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
28141cc406Sopenharmony_ci   account of linking the SANE library code into it.
29141cc406Sopenharmony_ci
30141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
31141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
32141cc406Sopenharmony_ci   License.
33141cc406Sopenharmony_ci
34141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
35141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
36141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
37141cc406Sopenharmony_ci
38141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
39141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
40141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.  */
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ci#define BUILD 9
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci#include "../include/sane/config.h"
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#include <stdlib.h>
47141cc406Sopenharmony_ci#include <string.h>
48141cc406Sopenharmony_ci#include <stdio.h>
49141cc406Sopenharmony_ci#include <unistd.h>
50141cc406Sopenharmony_ci#include <fcntl.h>
51141cc406Sopenharmony_ci#include <errno.h>
52141cc406Sopenharmony_ci#include <sys/time.h>
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ci#include "../include/sane/sane.h"
55141cc406Sopenharmony_ci#include "../include/sane/sanei.h"
56141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci#define BACKEND_NAME	pnm
59141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
60141cc406Sopenharmony_ci
61141cc406Sopenharmony_ci#ifndef PATH_MAX
62141cc406Sopenharmony_ci# define PATH_MAX	1024
63141cc406Sopenharmony_ci#endif
64141cc406Sopenharmony_ci
65141cc406Sopenharmony_ci#define MAGIC	(void *)0xab730324
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_cistatic int is_open = 0;
68141cc406Sopenharmony_cistatic int rgb_comp = 0;
69141cc406Sopenharmony_cistatic int three_pass = 0;
70141cc406Sopenharmony_cistatic int hand_scanner = 0;
71141cc406Sopenharmony_cistatic int pass = 0;
72141cc406Sopenharmony_cistatic char filename[PATH_MAX] = "/tmp/input.ppm";
73141cc406Sopenharmony_cistatic SANE_Word status_none = SANE_TRUE;
74141cc406Sopenharmony_cistatic SANE_Word status_eof = SANE_FALSE;
75141cc406Sopenharmony_cistatic SANE_Word status_jammed = SANE_FALSE;
76141cc406Sopenharmony_cistatic SANE_Word status_nodocs = SANE_FALSE;
77141cc406Sopenharmony_cistatic SANE_Word status_coveropen = SANE_FALSE;
78141cc406Sopenharmony_cistatic SANE_Word status_ioerror = SANE_FALSE;
79141cc406Sopenharmony_cistatic SANE_Word status_nomem = SANE_FALSE;
80141cc406Sopenharmony_cistatic SANE_Word status_accessdenied = SANE_FALSE;
81141cc406Sopenharmony_cistatic SANE_Word test_option = 0;
82141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
83141cc406Sopenharmony_cistatic SANE_Word warming_up = SANE_FALSE;
84141cc406Sopenharmony_cistatic struct timeval start;
85141cc406Sopenharmony_ci#endif
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_cistatic SANE_Fixed bright = 0;
88141cc406Sopenharmony_cistatic SANE_Word res = 75;
89141cc406Sopenharmony_cistatic SANE_Fixed contr = 0;
90141cc406Sopenharmony_cistatic SANE_Bool gray = SANE_FALSE;
91141cc406Sopenharmony_cistatic SANE_Bool usegamma = SANE_FALSE;
92141cc406Sopenharmony_cistatic SANE_Word gamma[4][256];
93141cc406Sopenharmony_cistatic enum
94141cc406Sopenharmony_ci{
95141cc406Sopenharmony_ci  ppm_bitmap,
96141cc406Sopenharmony_ci  ppm_greyscale,
97141cc406Sopenharmony_ci  ppm_color
98141cc406Sopenharmony_ci}
99141cc406Sopenharmony_cippm_type = ppm_color;
100141cc406Sopenharmony_cistatic FILE *infile = NULL;
101141cc406Sopenharmony_cistatic const SANE_Word resbit_list[] = {
102141cc406Sopenharmony_ci  17,
103141cc406Sopenharmony_ci  75, 90, 100, 120, 135, 150, 165, 180, 195,
104141cc406Sopenharmony_ci  200, 210, 225, 240, 255, 270, 285, 300
105141cc406Sopenharmony_ci};
106141cc406Sopenharmony_cistatic const SANE_Range percentage_range = {
107141cc406Sopenharmony_ci  SANE_FIX(-100),	/* minimum */
108141cc406Sopenharmony_ci  SANE_FIX(100),	/* maximum */
109141cc406Sopenharmony_ci  SANE_FIX(0)           /* quantization */
110141cc406Sopenharmony_ci};
111141cc406Sopenharmony_cistatic const SANE_Range gamma_range = {
112141cc406Sopenharmony_ci  0,				/* minimum */
113141cc406Sopenharmony_ci  255,				/* maximum */
114141cc406Sopenharmony_ci  0				/* quantization */
115141cc406Sopenharmony_ci};
116141cc406Sopenharmony_citypedef enum
117141cc406Sopenharmony_ci{
118141cc406Sopenharmony_ci  opt_num_opts = 0,
119141cc406Sopenharmony_ci  opt_source_group,
120141cc406Sopenharmony_ci  opt_filename,
121141cc406Sopenharmony_ci  opt_resolution,
122141cc406Sopenharmony_ci  opt_enhancement_group,
123141cc406Sopenharmony_ci  opt_brightness,
124141cc406Sopenharmony_ci  opt_contrast,
125141cc406Sopenharmony_ci  opt_grayify,
126141cc406Sopenharmony_ci  opt_three_pass,
127141cc406Sopenharmony_ci  opt_hand_scanner,
128141cc406Sopenharmony_ci  opt_default_enhancements,
129141cc406Sopenharmony_ci  opt_read_only,
130141cc406Sopenharmony_ci  opt_gamma_group,
131141cc406Sopenharmony_ci  opt_custom_gamma,
132141cc406Sopenharmony_ci  opt_gamma,
133141cc406Sopenharmony_ci  opt_gamma_r,
134141cc406Sopenharmony_ci  opt_gamma_g,
135141cc406Sopenharmony_ci  opt_gamma_b,
136141cc406Sopenharmony_ci  opt_status_group,
137141cc406Sopenharmony_ci  opt_status,
138141cc406Sopenharmony_ci  opt_status_eof,
139141cc406Sopenharmony_ci  opt_status_jammed,
140141cc406Sopenharmony_ci  opt_status_nodocs,
141141cc406Sopenharmony_ci  opt_status_coveropen,
142141cc406Sopenharmony_ci  opt_status_ioerror,
143141cc406Sopenharmony_ci  opt_status_nomem,
144141cc406Sopenharmony_ci  opt_status_accessdenied,
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci  /* must come last: */
147141cc406Sopenharmony_ci  num_options
148141cc406Sopenharmony_ci}
149141cc406Sopenharmony_cipnm_opts;
150141cc406Sopenharmony_ci
151141cc406Sopenharmony_cistatic SANE_Option_Descriptor sod[] = {
152141cc406Sopenharmony_ci  {				/* opt_num_opts */
153141cc406Sopenharmony_ci   SANE_NAME_NUM_OPTIONS,
154141cc406Sopenharmony_ci   SANE_TITLE_NUM_OPTIONS,
155141cc406Sopenharmony_ci   SANE_DESC_NUM_OPTIONS,
156141cc406Sopenharmony_ci   SANE_TYPE_INT,
157141cc406Sopenharmony_ci   SANE_UNIT_NONE,
158141cc406Sopenharmony_ci   sizeof (SANE_Word),
159141cc406Sopenharmony_ci   SANE_CAP_SOFT_DETECT,
160141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
161141cc406Sopenharmony_ci   {NULL}
162141cc406Sopenharmony_ci   }
163141cc406Sopenharmony_ci  ,
164141cc406Sopenharmony_ci  {				/* opt_source_group */
165141cc406Sopenharmony_ci   "",
166141cc406Sopenharmony_ci   SANE_I18N ("Source Selection"),
167141cc406Sopenharmony_ci   "",
168141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
169141cc406Sopenharmony_ci   SANE_UNIT_NONE,
170141cc406Sopenharmony_ci   0,
171141cc406Sopenharmony_ci   0,
172141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
173141cc406Sopenharmony_ci   {NULL}
174141cc406Sopenharmony_ci   }
175141cc406Sopenharmony_ci  ,
176141cc406Sopenharmony_ci  {				/* opt_filename */
177141cc406Sopenharmony_ci   SANE_NAME_FILE,
178141cc406Sopenharmony_ci   SANE_TITLE_FILE,
179141cc406Sopenharmony_ci   SANE_DESC_FILE,
180141cc406Sopenharmony_ci   SANE_TYPE_STRING,
181141cc406Sopenharmony_ci   SANE_UNIT_NONE,
182141cc406Sopenharmony_ci   sizeof (filename),
183141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
184141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
185141cc406Sopenharmony_ci   {NULL}
186141cc406Sopenharmony_ci   }
187141cc406Sopenharmony_ci  ,
188141cc406Sopenharmony_ci  {
189141cc406Sopenharmony_ci   /* opt_resolution */
190141cc406Sopenharmony_ci   SANE_NAME_SCAN_RESOLUTION,
191141cc406Sopenharmony_ci   SANE_TITLE_SCAN_RESOLUTION,
192141cc406Sopenharmony_ci   SANE_DESC_SCAN_RESOLUTION,
193141cc406Sopenharmony_ci   SANE_TYPE_INT,
194141cc406Sopenharmony_ci   SANE_UNIT_DPI,
195141cc406Sopenharmony_ci   sizeof (SANE_Word),
196141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC,
197141cc406Sopenharmony_ci   SANE_CONSTRAINT_WORD_LIST,
198141cc406Sopenharmony_ci   {(SANE_String_Const *) resbit_list}
199141cc406Sopenharmony_ci   }
200141cc406Sopenharmony_ci  ,
201141cc406Sopenharmony_ci  {				/* opt_enhancement_group */
202141cc406Sopenharmony_ci   "",
203141cc406Sopenharmony_ci   SANE_I18N ("Image Enhancement"),
204141cc406Sopenharmony_ci   "",
205141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
206141cc406Sopenharmony_ci   SANE_UNIT_NONE,
207141cc406Sopenharmony_ci   0,
208141cc406Sopenharmony_ci   0,
209141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
210141cc406Sopenharmony_ci   {NULL}
211141cc406Sopenharmony_ci   }
212141cc406Sopenharmony_ci  ,
213141cc406Sopenharmony_ci  {				/* opt_brightness */
214141cc406Sopenharmony_ci   SANE_NAME_BRIGHTNESS,
215141cc406Sopenharmony_ci   SANE_TITLE_BRIGHTNESS,
216141cc406Sopenharmony_ci   SANE_DESC_BRIGHTNESS,
217141cc406Sopenharmony_ci   SANE_TYPE_FIXED,
218141cc406Sopenharmony_ci   SANE_UNIT_PERCENT,
219141cc406Sopenharmony_ci   sizeof (SANE_Word),
220141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
221141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
222141cc406Sopenharmony_ci   {(SANE_String_Const *) & percentage_range}	/* this is ANSI conformant! */
223141cc406Sopenharmony_ci   }
224141cc406Sopenharmony_ci  ,
225141cc406Sopenharmony_ci  {				/* opt_contrast */
226141cc406Sopenharmony_ci   SANE_NAME_CONTRAST,
227141cc406Sopenharmony_ci   SANE_TITLE_CONTRAST,
228141cc406Sopenharmony_ci   SANE_DESC_CONTRAST,
229141cc406Sopenharmony_ci   SANE_TYPE_FIXED,
230141cc406Sopenharmony_ci   SANE_UNIT_PERCENT,
231141cc406Sopenharmony_ci   sizeof (SANE_Word),
232141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
233141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
234141cc406Sopenharmony_ci   {(SANE_String_Const *) & percentage_range}	/* this is ANSI conformant! */
235141cc406Sopenharmony_ci   }
236141cc406Sopenharmony_ci  ,
237141cc406Sopenharmony_ci  {				/* opt_grayify */
238141cc406Sopenharmony_ci   "grayify",
239141cc406Sopenharmony_ci   SANE_I18N ("Grayify"),
240141cc406Sopenharmony_ci   SANE_I18N ("Load the image as grayscale."),
241141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
242141cc406Sopenharmony_ci   SANE_UNIT_NONE,
243141cc406Sopenharmony_ci   sizeof (SANE_Word),
244141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
245141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
246141cc406Sopenharmony_ci   {NULL}
247141cc406Sopenharmony_ci   }
248141cc406Sopenharmony_ci  ,
249141cc406Sopenharmony_ci  {				/* opt_three_pass */
250141cc406Sopenharmony_ci   "three-pass",
251141cc406Sopenharmony_ci   SANE_I18N ("Three-Pass Simulation"),
252141cc406Sopenharmony_ci   SANE_I18N
253141cc406Sopenharmony_ci   ("Simulate a three-pass scanner by returning 3 separate frames.  "
254141cc406Sopenharmony_ci    "For kicks, it returns green, then blue, then red."),
255141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
256141cc406Sopenharmony_ci   SANE_UNIT_NONE,
257141cc406Sopenharmony_ci   sizeof (SANE_Word),
258141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
259141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
260141cc406Sopenharmony_ci   {NULL}
261141cc406Sopenharmony_ci   }
262141cc406Sopenharmony_ci  ,
263141cc406Sopenharmony_ci  {				/* opt_hand_scanner */
264141cc406Sopenharmony_ci   "hand-scanner",
265141cc406Sopenharmony_ci   SANE_I18N ("Hand-Scanner Simulation"),
266141cc406Sopenharmony_ci   SANE_I18N ("Simulate a hand-scanner.  Hand-scanners often do not know the "
267141cc406Sopenharmony_ci	      "image height a priori.  Instead, they return a height of -1.  "
268141cc406Sopenharmony_ci	      "Setting this option allows one to test whether a frontend can "
269141cc406Sopenharmony_ci	      "handle this correctly."),
270141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
271141cc406Sopenharmony_ci   SANE_UNIT_NONE,
272141cc406Sopenharmony_ci   sizeof (SANE_Word),
273141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
274141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
275141cc406Sopenharmony_ci   {NULL}
276141cc406Sopenharmony_ci   }
277141cc406Sopenharmony_ci  ,
278141cc406Sopenharmony_ci  {				/* opt_default_enhancements */
279141cc406Sopenharmony_ci   "default-enhancements",
280141cc406Sopenharmony_ci   SANE_I18N ("Defaults"),
281141cc406Sopenharmony_ci   SANE_I18N ("Set default values for enhancement controls (brightness & "
282141cc406Sopenharmony_ci	      "contrast)."),
283141cc406Sopenharmony_ci   SANE_TYPE_BUTTON,
284141cc406Sopenharmony_ci   SANE_UNIT_NONE,
285141cc406Sopenharmony_ci   0,
286141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
287141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
288141cc406Sopenharmony_ci   {NULL}
289141cc406Sopenharmony_ci   }
290141cc406Sopenharmony_ci  ,
291141cc406Sopenharmony_ci  {				/* opt_read_only */
292141cc406Sopenharmony_ci   "read-only",
293141cc406Sopenharmony_ci   SANE_I18N ("Read only test-option"),
294141cc406Sopenharmony_ci   SANE_I18N ("Let's see whether frontends can treat this right"),
295141cc406Sopenharmony_ci   SANE_TYPE_INT,
296141cc406Sopenharmony_ci   SANE_UNIT_PERCENT,
297141cc406Sopenharmony_ci   sizeof (SANE_Word),
298141cc406Sopenharmony_ci   SANE_CAP_SOFT_DETECT,
299141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
300141cc406Sopenharmony_ci   {NULL}
301141cc406Sopenharmony_ci   }
302141cc406Sopenharmony_ci  ,
303141cc406Sopenharmony_ci  {				/* opt_gamma_group */
304141cc406Sopenharmony_ci   "",
305141cc406Sopenharmony_ci   SANE_I18N ("Gamma Tables"),
306141cc406Sopenharmony_ci   "",
307141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
308141cc406Sopenharmony_ci   SANE_UNIT_NONE,
309141cc406Sopenharmony_ci   0,
310141cc406Sopenharmony_ci   0,
311141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
312141cc406Sopenharmony_ci   {NULL}
313141cc406Sopenharmony_ci   }
314141cc406Sopenharmony_ci  ,
315141cc406Sopenharmony_ci  {				/* opt_custom_gamma */
316141cc406Sopenharmony_ci   SANE_NAME_CUSTOM_GAMMA,
317141cc406Sopenharmony_ci   SANE_TITLE_CUSTOM_GAMMA,
318141cc406Sopenharmony_ci   SANE_DESC_CUSTOM_GAMMA,
319141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
320141cc406Sopenharmony_ci   SANE_UNIT_NONE,
321141cc406Sopenharmony_ci   sizeof (SANE_Word),
322141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
323141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
324141cc406Sopenharmony_ci   {NULL}
325141cc406Sopenharmony_ci   }
326141cc406Sopenharmony_ci  ,
327141cc406Sopenharmony_ci  {				/* opt_gamma */
328141cc406Sopenharmony_ci   SANE_NAME_GAMMA_VECTOR,
329141cc406Sopenharmony_ci   SANE_TITLE_GAMMA_VECTOR,
330141cc406Sopenharmony_ci   SANE_DESC_GAMMA_VECTOR,
331141cc406Sopenharmony_ci   SANE_TYPE_INT,
332141cc406Sopenharmony_ci   SANE_UNIT_NONE,
333141cc406Sopenharmony_ci   sizeof (SANE_Word) * 256,
334141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
335141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
336141cc406Sopenharmony_ci   {(SANE_String_Const *) & gamma_range}
337141cc406Sopenharmony_ci   }
338141cc406Sopenharmony_ci  ,
339141cc406Sopenharmony_ci  {				/* opt_gamma_r */
340141cc406Sopenharmony_ci   SANE_NAME_GAMMA_VECTOR_R,
341141cc406Sopenharmony_ci   SANE_TITLE_GAMMA_VECTOR_R,
342141cc406Sopenharmony_ci   SANE_DESC_GAMMA_VECTOR_R,
343141cc406Sopenharmony_ci   SANE_TYPE_INT,
344141cc406Sopenharmony_ci   SANE_UNIT_NONE,
345141cc406Sopenharmony_ci   sizeof (SANE_Word) * 256,
346141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
347141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
348141cc406Sopenharmony_ci   {(SANE_String_Const *) & gamma_range}
349141cc406Sopenharmony_ci   }
350141cc406Sopenharmony_ci  ,
351141cc406Sopenharmony_ci  {				/* opt_gamma_g */
352141cc406Sopenharmony_ci   SANE_NAME_GAMMA_VECTOR_G,
353141cc406Sopenharmony_ci   SANE_TITLE_GAMMA_VECTOR_G,
354141cc406Sopenharmony_ci   SANE_DESC_GAMMA_VECTOR_G,
355141cc406Sopenharmony_ci   SANE_TYPE_INT,
356141cc406Sopenharmony_ci   SANE_UNIT_NONE,
357141cc406Sopenharmony_ci   sizeof (SANE_Word) * 256,
358141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
359141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
360141cc406Sopenharmony_ci   {(SANE_String_Const *) & gamma_range}
361141cc406Sopenharmony_ci   }
362141cc406Sopenharmony_ci  ,
363141cc406Sopenharmony_ci  {				/* opt_gamma_b */
364141cc406Sopenharmony_ci   SANE_NAME_GAMMA_VECTOR_B,
365141cc406Sopenharmony_ci   SANE_TITLE_GAMMA_VECTOR_B,
366141cc406Sopenharmony_ci   SANE_DESC_GAMMA_VECTOR_B,
367141cc406Sopenharmony_ci   SANE_TYPE_INT,
368141cc406Sopenharmony_ci   SANE_UNIT_NONE,
369141cc406Sopenharmony_ci   sizeof (SANE_Word) * 256,
370141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
371141cc406Sopenharmony_ci   SANE_CONSTRAINT_RANGE,
372141cc406Sopenharmony_ci   {(SANE_String_Const *) & gamma_range}
373141cc406Sopenharmony_ci   }
374141cc406Sopenharmony_ci  ,
375141cc406Sopenharmony_ci  {				/* opt_status_group */
376141cc406Sopenharmony_ci   "",
377141cc406Sopenharmony_ci   SANE_I18N ("Status Code Simulation"),
378141cc406Sopenharmony_ci   "",
379141cc406Sopenharmony_ci   SANE_TYPE_GROUP,
380141cc406Sopenharmony_ci   SANE_UNIT_NONE,
381141cc406Sopenharmony_ci   0,
382141cc406Sopenharmony_ci   SANE_CAP_ADVANCED,
383141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
384141cc406Sopenharmony_ci   {NULL}
385141cc406Sopenharmony_ci   }
386141cc406Sopenharmony_ci  ,
387141cc406Sopenharmony_ci  {				/* opt_status */
388141cc406Sopenharmony_ci   "status",
389141cc406Sopenharmony_ci   SANE_I18N ("Do not force status code"),
390141cc406Sopenharmony_ci   SANE_I18N ("Do not force the backend to return a status code."),
391141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
392141cc406Sopenharmony_ci   SANE_UNIT_NONE,
393141cc406Sopenharmony_ci   sizeof (SANE_Bool),
394141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
395141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
396141cc406Sopenharmony_ci   {NULL}
397141cc406Sopenharmony_ci   }
398141cc406Sopenharmony_ci  ,
399141cc406Sopenharmony_ci  {				/* opt_status_eof */
400141cc406Sopenharmony_ci   "status-eof",
401141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_EOF"),
402141cc406Sopenharmony_ci   SANE_I18N ("Force the backend to return the status code SANE_STATUS_EOF "
403141cc406Sopenharmony_ci	      "after sane_read() has been called."),
404141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
405141cc406Sopenharmony_ci   SANE_UNIT_NONE,
406141cc406Sopenharmony_ci   sizeof (SANE_Bool),
407141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
408141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
409141cc406Sopenharmony_ci   {NULL}
410141cc406Sopenharmony_ci   }
411141cc406Sopenharmony_ci  ,
412141cc406Sopenharmony_ci  {				/* opt_status_jammed */
413141cc406Sopenharmony_ci   "status-jammed",
414141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_JAMMED"),
415141cc406Sopenharmony_ci   SANE_I18N
416141cc406Sopenharmony_ci   ("Force the backend to return the status code SANE_STATUS_JAMMED "
417141cc406Sopenharmony_ci    "after sane_read() has been called."),
418141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
419141cc406Sopenharmony_ci   SANE_UNIT_NONE,
420141cc406Sopenharmony_ci   sizeof (SANE_Bool),
421141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
422141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
423141cc406Sopenharmony_ci   {NULL}
424141cc406Sopenharmony_ci   }
425141cc406Sopenharmony_ci  ,
426141cc406Sopenharmony_ci  {				/* opt_status_nodocs */
427141cc406Sopenharmony_ci   "status-nodocs",
428141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_NO_DOCS"),
429141cc406Sopenharmony_ci   SANE_I18N ("Force the backend to return the status code "
430141cc406Sopenharmony_ci	      "SANE_STATUS_NO_DOCS after sane_read() has been called."),
431141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
432141cc406Sopenharmony_ci   SANE_UNIT_NONE,
433141cc406Sopenharmony_ci   sizeof (SANE_Bool),
434141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
435141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
436141cc406Sopenharmony_ci   {NULL}
437141cc406Sopenharmony_ci   }
438141cc406Sopenharmony_ci  ,
439141cc406Sopenharmony_ci  {				/* opt_status_coveropen */
440141cc406Sopenharmony_ci   "status-coveropen",
441141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_COVER_OPEN"),
442141cc406Sopenharmony_ci   SANE_I18N ("Force the backend to return the status code "
443141cc406Sopenharmony_ci	      "SANE_STATUS_COVER_OPEN after sane_read() has been called."),
444141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
445141cc406Sopenharmony_ci   SANE_UNIT_NONE,
446141cc406Sopenharmony_ci   sizeof (SANE_Bool),
447141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
448141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
449141cc406Sopenharmony_ci   {NULL}
450141cc406Sopenharmony_ci   }
451141cc406Sopenharmony_ci  ,
452141cc406Sopenharmony_ci  {				/* opt_status_ioerror */
453141cc406Sopenharmony_ci   "status-ioerror",
454141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_IO_ERROR"),
455141cc406Sopenharmony_ci   SANE_I18N ("Force the backend to return the status code "
456141cc406Sopenharmony_ci	      "SANE_STATUS_IO_ERROR after sane_read() has been called."),
457141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
458141cc406Sopenharmony_ci   SANE_UNIT_NONE,
459141cc406Sopenharmony_ci   sizeof (SANE_Bool),
460141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
461141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
462141cc406Sopenharmony_ci   {NULL}
463141cc406Sopenharmony_ci   }
464141cc406Sopenharmony_ci  ,
465141cc406Sopenharmony_ci  {				/* opt_status_nomem */
466141cc406Sopenharmony_ci   "status-nomem",
467141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_NO_MEM"),
468141cc406Sopenharmony_ci   SANE_I18N
469141cc406Sopenharmony_ci   ("Force the backend to return the status code SANE_STATUS_NO_MEM "
470141cc406Sopenharmony_ci    "after sane_read() has been called."),
471141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
472141cc406Sopenharmony_ci   SANE_UNIT_NONE,
473141cc406Sopenharmony_ci   sizeof (SANE_Bool),
474141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
475141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
476141cc406Sopenharmony_ci   {NULL}
477141cc406Sopenharmony_ci   }
478141cc406Sopenharmony_ci  ,
479141cc406Sopenharmony_ci  {				/* opt_status_accessdenied */
480141cc406Sopenharmony_ci   "status-accessdenied",
481141cc406Sopenharmony_ci   SANE_I18N ("Return SANE_STATUS_ACCESS_DENIED"),
482141cc406Sopenharmony_ci   SANE_I18N ("Force the backend to return the status code "
483141cc406Sopenharmony_ci	      "SANE_STATUS_ACCESS_DENIED after sane_read() has been called."),
484141cc406Sopenharmony_ci   SANE_TYPE_BOOL,
485141cc406Sopenharmony_ci   SANE_UNIT_NONE,
486141cc406Sopenharmony_ci   sizeof (SANE_Bool),
487141cc406Sopenharmony_ci   SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
488141cc406Sopenharmony_ci   SANE_CONSTRAINT_NONE,
489141cc406Sopenharmony_ci   {NULL}
490141cc406Sopenharmony_ci   }
491141cc406Sopenharmony_ci};
492141cc406Sopenharmony_ci
493141cc406Sopenharmony_cistatic SANE_Parameters parms = {
494141cc406Sopenharmony_ci  SANE_FRAME_RGB,
495141cc406Sopenharmony_ci  0,
496141cc406Sopenharmony_ci  0,				/* Number of bytes returned per scan line: */
497141cc406Sopenharmony_ci  0,				/* Number of pixels per scan line.  */
498141cc406Sopenharmony_ci  0,				/* Number of lines for the current scan.  */
499141cc406Sopenharmony_ci  8,				/* Number of bits per sample. */
500141cc406Sopenharmony_ci};
501141cc406Sopenharmony_ci
502141cc406Sopenharmony_ci/* This library is a demo implementation of a SANE backend.  It
503141cc406Sopenharmony_ci   implements a virtual device, a PNM file-filter. */
504141cc406Sopenharmony_ciSANE_Status
505141cc406Sopenharmony_cisane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
506141cc406Sopenharmony_ci{
507141cc406Sopenharmony_ci  DBG_INIT ();
508141cc406Sopenharmony_ci
509141cc406Sopenharmony_ci  DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
510141cc406Sopenharmony_ci       version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
511141cc406Sopenharmony_ci  DBG (1, "sane_init: SANE pnm backend version %d.%d.%d from %s\n",
512141cc406Sopenharmony_ci       SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
513141cc406Sopenharmony_ci
514141cc406Sopenharmony_ci  if (version_code)
515141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
516141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
517141cc406Sopenharmony_ci}
518141cc406Sopenharmony_ci
519141cc406Sopenharmony_civoid
520141cc406Sopenharmony_cisane_exit (void)
521141cc406Sopenharmony_ci{
522141cc406Sopenharmony_ci  DBG (2, "sane_exit\n");
523141cc406Sopenharmony_ci  return;
524141cc406Sopenharmony_ci}
525141cc406Sopenharmony_ci
526141cc406Sopenharmony_ci/* Device select/open/close */
527141cc406Sopenharmony_ci
528141cc406Sopenharmony_cistatic const SANE_Device dev[] = {
529141cc406Sopenharmony_ci  {
530141cc406Sopenharmony_ci   "0",
531141cc406Sopenharmony_ci   "Noname",
532141cc406Sopenharmony_ci   "PNM file reader",
533141cc406Sopenharmony_ci   "virtual device"},
534141cc406Sopenharmony_ci  {
535141cc406Sopenharmony_ci   "1",
536141cc406Sopenharmony_ci   "Noname",
537141cc406Sopenharmony_ci   "PNM file reader",
538141cc406Sopenharmony_ci   "virtual device"},
539141cc406Sopenharmony_ci#ifdef SANE_STATUS_HW_LOCKED
540141cc406Sopenharmony_ci  {
541141cc406Sopenharmony_ci   "locked",
542141cc406Sopenharmony_ci   "Noname",
543141cc406Sopenharmony_ci   "Hardware locked",
544141cc406Sopenharmony_ci   "virtual device"},
545141cc406Sopenharmony_ci#endif
546141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
547141cc406Sopenharmony_ci  {
548141cc406Sopenharmony_ci   "warmup",
549141cc406Sopenharmony_ci   "Noname",
550141cc406Sopenharmony_ci   "Always warming up",
551141cc406Sopenharmony_ci   "virtual device"},
552141cc406Sopenharmony_ci#endif
553141cc406Sopenharmony_ci};
554141cc406Sopenharmony_ci
555141cc406Sopenharmony_ciSANE_Status
556141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
557141cc406Sopenharmony_ci{
558141cc406Sopenharmony_ci  static const SANE_Device *devlist[] = {
559141cc406Sopenharmony_ci    dev + 0, dev + 1,
560141cc406Sopenharmony_ci#ifdef SANE_STATUS_HW_LOCKED
561141cc406Sopenharmony_ci    dev + 2,
562141cc406Sopenharmony_ci#endif
563141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
564141cc406Sopenharmony_ci    dev + 3,
565141cc406Sopenharmony_ci#endif
566141cc406Sopenharmony_ci    0
567141cc406Sopenharmony_ci  };
568141cc406Sopenharmony_ci
569141cc406Sopenharmony_ci  DBG (2, "sane_get_devices: local_only = %d\n", local_only);
570141cc406Sopenharmony_ci  *device_list = devlist;
571141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
572141cc406Sopenharmony_ci}
573141cc406Sopenharmony_ci
574141cc406Sopenharmony_ciSANE_Status
575141cc406Sopenharmony_cisane_open (SANE_String_Const devicename, SANE_Handle * handle)
576141cc406Sopenharmony_ci{
577141cc406Sopenharmony_ci  int i;
578141cc406Sopenharmony_ci
579141cc406Sopenharmony_ci  if (!devicename)
580141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
581141cc406Sopenharmony_ci  DBG (2, "sane_open: devicename = \"%s\"\n", devicename);
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci  if (!devicename[0])
584141cc406Sopenharmony_ci    i = 0;
585141cc406Sopenharmony_ci  else
586141cc406Sopenharmony_ci    for (i = 0; i < NELEMS (dev); ++i)
587141cc406Sopenharmony_ci      if (strcmp (devicename, dev[i].name) == 0)
588141cc406Sopenharmony_ci	break;
589141cc406Sopenharmony_ci  if (i >= NELEMS (dev))
590141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
591141cc406Sopenharmony_ci
592141cc406Sopenharmony_ci  if (is_open)
593141cc406Sopenharmony_ci    return SANE_STATUS_DEVICE_BUSY;
594141cc406Sopenharmony_ci
595141cc406Sopenharmony_ci  is_open = 1;
596141cc406Sopenharmony_ci  *handle = MAGIC;
597141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
598141cc406Sopenharmony_ci    {
599141cc406Sopenharmony_ci      gamma[0][i] = i;
600141cc406Sopenharmony_ci      gamma[1][i] = i;
601141cc406Sopenharmony_ci      gamma[2][i] = i;
602141cc406Sopenharmony_ci      gamma[3][i] = i;
603141cc406Sopenharmony_ci    }
604141cc406Sopenharmony_ci
605141cc406Sopenharmony_ci#ifdef SANE_STATUS_HW_LOCKED
606141cc406Sopenharmony_ci  if(strncmp(devicename,"locked",6)==0)
607141cc406Sopenharmony_ci    return SANE_STATUS_HW_LOCKED;
608141cc406Sopenharmony_ci#endif
609141cc406Sopenharmony_ci
610141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
611141cc406Sopenharmony_ci  if(strncmp(devicename,"warmup",6)==0)
612141cc406Sopenharmony_ci    {
613141cc406Sopenharmony_ci      warming_up = SANE_TRUE;
614141cc406Sopenharmony_ci      start.tv_sec = 0;
615141cc406Sopenharmony_ci    }
616141cc406Sopenharmony_ci#endif
617141cc406Sopenharmony_ci
618141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
619141cc406Sopenharmony_ci}
620141cc406Sopenharmony_ci
621141cc406Sopenharmony_civoid
622141cc406Sopenharmony_cisane_close (SANE_Handle handle)
623141cc406Sopenharmony_ci{
624141cc406Sopenharmony_ci  DBG (2, "sane_close\n");
625141cc406Sopenharmony_ci  if (handle == MAGIC)
626141cc406Sopenharmony_ci    is_open = 0;
627141cc406Sopenharmony_ci}
628141cc406Sopenharmony_ci
629141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
630141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
631141cc406Sopenharmony_ci{
632141cc406Sopenharmony_ci  DBG (2, "sane_get_option_descriptor: option = %d\n", option);
633141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
634141cc406Sopenharmony_ci    return NULL;		/* wrong device */
635141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
636141cc406Sopenharmony_ci    return NULL;
637141cc406Sopenharmony_ci  return &sod[option];
638141cc406Sopenharmony_ci}
639141cc406Sopenharmony_ci
640141cc406Sopenharmony_ciSANE_Status
641141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
642141cc406Sopenharmony_ci		     SANE_Action action, void *value, SANE_Int * info)
643141cc406Sopenharmony_ci{
644141cc406Sopenharmony_ci  SANE_Int myinfo = 0;
645141cc406Sopenharmony_ci  SANE_Status status;
646141cc406Sopenharmony_ci  int v;
647141cc406Sopenharmony_ci  v = 75;
648141cc406Sopenharmony_ci
649141cc406Sopenharmony_ci  DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
650141cc406Sopenharmony_ci       handle, option, action, value, (void *) info);
651141cc406Sopenharmony_ci
652141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
653141cc406Sopenharmony_ci    {
654141cc406Sopenharmony_ci      DBG (1, "sane_control_option: unknown handle or not open\n");
655141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;	/* Unknown handle ... */
656141cc406Sopenharmony_ci    }
657141cc406Sopenharmony_ci
658141cc406Sopenharmony_ci  if (option < 0 || option >= NELEMS (sod))
659141cc406Sopenharmony_ci    {
660141cc406Sopenharmony_ci      DBG (1, "sane_control_option: option %d < 0 or >= number of options\n",
661141cc406Sopenharmony_ci	   option);
662141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;	/* Unknown option ... */
663141cc406Sopenharmony_ci    }
664141cc406Sopenharmony_ci
665141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (sod[option].cap))
666141cc406Sopenharmony_ci    {
667141cc406Sopenharmony_ci      DBG (4, "sane_control_option: option is inactive\n");
668141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
669141cc406Sopenharmony_ci    }
670141cc406Sopenharmony_ci
671141cc406Sopenharmony_ci  switch (action)
672141cc406Sopenharmony_ci    {
673141cc406Sopenharmony_ci    case SANE_ACTION_SET_AUTO:
674141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (sod[option].cap))
675141cc406Sopenharmony_ci	{
676141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: option is not settable\n");
677141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
678141cc406Sopenharmony_ci	}
679141cc406Sopenharmony_ci      status = sanei_constrain_value (sod + option, (void *) &v, &myinfo);
680141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
681141cc406Sopenharmony_ci	return status;
682141cc406Sopenharmony_ci      switch (option)
683141cc406Sopenharmony_ci	{
684141cc406Sopenharmony_ci	case opt_resolution:
685141cc406Sopenharmony_ci	  res = 75;
686141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
687141cc406Sopenharmony_ci	  break;
688141cc406Sopenharmony_ci	default:
689141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
690141cc406Sopenharmony_ci	}
691141cc406Sopenharmony_ci      break;
692141cc406Sopenharmony_ci    case SANE_ACTION_SET_VALUE:
693141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (sod[option].cap))
694141cc406Sopenharmony_ci	{
695141cc406Sopenharmony_ci	  DBG (4, "sane_control_option: option is not settable\n");
696141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
697141cc406Sopenharmony_ci	}
698141cc406Sopenharmony_ci      status = sanei_constrain_value (sod + option, value, &myinfo);
699141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
700141cc406Sopenharmony_ci	return status;
701141cc406Sopenharmony_ci      switch (option)
702141cc406Sopenharmony_ci	{
703141cc406Sopenharmony_ci	case opt_filename:
704141cc406Sopenharmony_ci	  if ((strlen (value) + 1) > sizeof (filename))
705141cc406Sopenharmony_ci	    return SANE_STATUS_NO_MEM;
706141cc406Sopenharmony_ci	  strcpy (filename, value);
707141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
708141cc406Sopenharmony_ci	  break;
709141cc406Sopenharmony_ci	case opt_resolution:
710141cc406Sopenharmony_ci	  res = *(SANE_Word *) value;
711141cc406Sopenharmony_ci	  break;
712141cc406Sopenharmony_ci	case opt_brightness:
713141cc406Sopenharmony_ci	  bright = *(SANE_Word *) value;
714141cc406Sopenharmony_ci	  break;
715141cc406Sopenharmony_ci	case opt_contrast:
716141cc406Sopenharmony_ci	  contr = *(SANE_Word *) value;
717141cc406Sopenharmony_ci	  break;
718141cc406Sopenharmony_ci	case opt_grayify:
719141cc406Sopenharmony_ci	  gray = !!*(SANE_Word *) value;
720141cc406Sopenharmony_ci	  if (usegamma)
721141cc406Sopenharmony_ci	    {
722141cc406Sopenharmony_ci	      if (gray)
723141cc406Sopenharmony_ci		{
724141cc406Sopenharmony_ci		  sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE;
725141cc406Sopenharmony_ci		  sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
726141cc406Sopenharmony_ci		  sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
727141cc406Sopenharmony_ci		  sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
728141cc406Sopenharmony_ci		}
729141cc406Sopenharmony_ci	      else
730141cc406Sopenharmony_ci		{
731141cc406Sopenharmony_ci		  sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
732141cc406Sopenharmony_ci		  sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE;
733141cc406Sopenharmony_ci		  sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE;
734141cc406Sopenharmony_ci		  sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE;
735141cc406Sopenharmony_ci		}
736141cc406Sopenharmony_ci	    }
737141cc406Sopenharmony_ci	  else
738141cc406Sopenharmony_ci	    {
739141cc406Sopenharmony_ci	      sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
740141cc406Sopenharmony_ci	      sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
741141cc406Sopenharmony_ci	      sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
742141cc406Sopenharmony_ci	      sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
743141cc406Sopenharmony_ci	    }
744141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
745141cc406Sopenharmony_ci	  break;
746141cc406Sopenharmony_ci	case opt_three_pass:
747141cc406Sopenharmony_ci	  three_pass = !!*(SANE_Word *) value;
748141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
749141cc406Sopenharmony_ci	  break;
750141cc406Sopenharmony_ci	case opt_hand_scanner:
751141cc406Sopenharmony_ci	  hand_scanner = !!*(SANE_Word *) value;
752141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_PARAMS;
753141cc406Sopenharmony_ci	  break;
754141cc406Sopenharmony_ci	case opt_default_enhancements:
755141cc406Sopenharmony_ci	  bright = contr = 0;
756141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
757141cc406Sopenharmony_ci	  break;
758141cc406Sopenharmony_ci	case opt_custom_gamma:
759141cc406Sopenharmony_ci	  usegamma = *(SANE_Word *) value;
760141cc406Sopenharmony_ci	  /* activate/deactivate gamma */
761141cc406Sopenharmony_ci	  if (usegamma)
762141cc406Sopenharmony_ci	    {
763141cc406Sopenharmony_ci	      test_option = 100;
764141cc406Sopenharmony_ci	      if (gray)
765141cc406Sopenharmony_ci		{
766141cc406Sopenharmony_ci		  sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE;
767141cc406Sopenharmony_ci		  sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
768141cc406Sopenharmony_ci		  sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
769141cc406Sopenharmony_ci		  sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
770141cc406Sopenharmony_ci		}
771141cc406Sopenharmony_ci	      else
772141cc406Sopenharmony_ci		{
773141cc406Sopenharmony_ci		  sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
774141cc406Sopenharmony_ci		  sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE;
775141cc406Sopenharmony_ci		  sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE;
776141cc406Sopenharmony_ci		  sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE;
777141cc406Sopenharmony_ci		}
778141cc406Sopenharmony_ci	    }
779141cc406Sopenharmony_ci	  else
780141cc406Sopenharmony_ci	    {
781141cc406Sopenharmony_ci	      test_option = 0;
782141cc406Sopenharmony_ci	      sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
783141cc406Sopenharmony_ci	      sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
784141cc406Sopenharmony_ci	      sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
785141cc406Sopenharmony_ci	      sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
786141cc406Sopenharmony_ci	    }
787141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
788141cc406Sopenharmony_ci	  break;
789141cc406Sopenharmony_ci	case opt_gamma:
790141cc406Sopenharmony_ci	  memcpy (&gamma[0][0], (SANE_Word *) value,
791141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
792141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
793141cc406Sopenharmony_ci	  break;
794141cc406Sopenharmony_ci	case opt_gamma_r:
795141cc406Sopenharmony_ci	  memcpy (&gamma[1][0], (SANE_Word *) value,
796141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
797141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
798141cc406Sopenharmony_ci	  break;
799141cc406Sopenharmony_ci	case opt_gamma_g:
800141cc406Sopenharmony_ci	  memcpy (&gamma[2][0], (SANE_Word *) value,
801141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
802141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
803141cc406Sopenharmony_ci	  break;
804141cc406Sopenharmony_ci	case opt_gamma_b:
805141cc406Sopenharmony_ci	  memcpy (&gamma[3][0], (SANE_Word *) value,
806141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
807141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
808141cc406Sopenharmony_ci	  break;
809141cc406Sopenharmony_ci	  /* status */
810141cc406Sopenharmony_ci	case opt_status:
811141cc406Sopenharmony_ci	  status_none = *(SANE_Word *) value;
812141cc406Sopenharmony_ci	  if (status_none)
813141cc406Sopenharmony_ci	    {
814141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
815141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
816141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
817141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
818141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
819141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
820141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
821141cc406Sopenharmony_ci	    }
822141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
823141cc406Sopenharmony_ci	  break;
824141cc406Sopenharmony_ci	case opt_status_eof:
825141cc406Sopenharmony_ci	  status_eof = *(SANE_Word *) value;
826141cc406Sopenharmony_ci	  if (status_eof)
827141cc406Sopenharmony_ci	    {
828141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
829141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
830141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
831141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
832141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
833141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
834141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
835141cc406Sopenharmony_ci	    }
836141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
837141cc406Sopenharmony_ci	  break;
838141cc406Sopenharmony_ci	case opt_status_jammed:
839141cc406Sopenharmony_ci	  status_jammed = *(SANE_Word *) value;
840141cc406Sopenharmony_ci	  if (status_jammed)
841141cc406Sopenharmony_ci	    {
842141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
843141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
844141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
845141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
846141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
847141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
848141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
849141cc406Sopenharmony_ci	    }
850141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
851141cc406Sopenharmony_ci	  break;
852141cc406Sopenharmony_ci	case opt_status_nodocs:
853141cc406Sopenharmony_ci	  status_nodocs = *(SANE_Word *) value;
854141cc406Sopenharmony_ci	  if (status_nodocs)
855141cc406Sopenharmony_ci	    {
856141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
857141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
858141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
859141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
860141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
861141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
862141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
863141cc406Sopenharmony_ci	    }
864141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
865141cc406Sopenharmony_ci	  break;
866141cc406Sopenharmony_ci	case opt_status_coveropen:
867141cc406Sopenharmony_ci	  status_coveropen = *(SANE_Word *) value;
868141cc406Sopenharmony_ci	  if (status_coveropen)
869141cc406Sopenharmony_ci	    {
870141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
871141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
872141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
873141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
874141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
875141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
876141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
877141cc406Sopenharmony_ci	    }
878141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
879141cc406Sopenharmony_ci	  break;
880141cc406Sopenharmony_ci	case opt_status_ioerror:
881141cc406Sopenharmony_ci	  status_ioerror = *(SANE_Word *) value;
882141cc406Sopenharmony_ci	  if (status_ioerror)
883141cc406Sopenharmony_ci	    {
884141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
885141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
886141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
887141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
888141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
889141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
890141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
891141cc406Sopenharmony_ci	    }
892141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
893141cc406Sopenharmony_ci	  break;
894141cc406Sopenharmony_ci	case opt_status_nomem:
895141cc406Sopenharmony_ci	  status_nomem = *(SANE_Word *) value;
896141cc406Sopenharmony_ci	  if (status_nomem)
897141cc406Sopenharmony_ci	    {
898141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
899141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
900141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
901141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
902141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
903141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
904141cc406Sopenharmony_ci	      status_accessdenied = SANE_FALSE;
905141cc406Sopenharmony_ci	    }
906141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
907141cc406Sopenharmony_ci	  break;
908141cc406Sopenharmony_ci	case opt_status_accessdenied:
909141cc406Sopenharmony_ci	  status_accessdenied = *(SANE_Word *) value;
910141cc406Sopenharmony_ci	  if (status_accessdenied)
911141cc406Sopenharmony_ci	    {
912141cc406Sopenharmony_ci	      status_eof = SANE_FALSE;
913141cc406Sopenharmony_ci	      status_jammed = SANE_FALSE;
914141cc406Sopenharmony_ci	      status_nodocs = SANE_FALSE;
915141cc406Sopenharmony_ci	      status_coveropen = SANE_FALSE;
916141cc406Sopenharmony_ci	      status_ioerror = SANE_FALSE;
917141cc406Sopenharmony_ci	      status_nomem = SANE_FALSE;
918141cc406Sopenharmony_ci	      status_none = SANE_FALSE;
919141cc406Sopenharmony_ci	    }
920141cc406Sopenharmony_ci	  myinfo |= SANE_INFO_RELOAD_OPTIONS;
921141cc406Sopenharmony_ci	  break;
922141cc406Sopenharmony_ci	default:
923141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
924141cc406Sopenharmony_ci	}
925141cc406Sopenharmony_ci      break;
926141cc406Sopenharmony_ci    case SANE_ACTION_GET_VALUE:
927141cc406Sopenharmony_ci      switch (option)
928141cc406Sopenharmony_ci	{
929141cc406Sopenharmony_ci	case opt_num_opts:
930141cc406Sopenharmony_ci	  *(SANE_Word *) value = NELEMS (sod);
931141cc406Sopenharmony_ci	  break;
932141cc406Sopenharmony_ci	case opt_filename:
933141cc406Sopenharmony_ci	  strcpy (value, filename);
934141cc406Sopenharmony_ci	  break;
935141cc406Sopenharmony_ci	case opt_resolution:
936141cc406Sopenharmony_ci	  *(SANE_Word *) value = res;
937141cc406Sopenharmony_ci	  break;
938141cc406Sopenharmony_ci	case opt_brightness:
939141cc406Sopenharmony_ci	  *(SANE_Word *) value = bright;
940141cc406Sopenharmony_ci	  break;
941141cc406Sopenharmony_ci	case opt_contrast:
942141cc406Sopenharmony_ci	  *(SANE_Word *) value = contr;
943141cc406Sopenharmony_ci	  break;
944141cc406Sopenharmony_ci	case opt_grayify:
945141cc406Sopenharmony_ci	  *(SANE_Word *) value = gray;
946141cc406Sopenharmony_ci	  break;
947141cc406Sopenharmony_ci	case opt_three_pass:
948141cc406Sopenharmony_ci	  *(SANE_Word *) value = three_pass;
949141cc406Sopenharmony_ci	  break;
950141cc406Sopenharmony_ci	case opt_hand_scanner:
951141cc406Sopenharmony_ci	  *(SANE_Word *) value = hand_scanner;
952141cc406Sopenharmony_ci	  break;
953141cc406Sopenharmony_ci	case opt_read_only:
954141cc406Sopenharmony_ci	  *(SANE_Word *) value = test_option;
955141cc406Sopenharmony_ci	  break;
956141cc406Sopenharmony_ci	case opt_custom_gamma:
957141cc406Sopenharmony_ci	  *(SANE_Word *) value = usegamma;
958141cc406Sopenharmony_ci	  break;
959141cc406Sopenharmony_ci	case opt_gamma:
960141cc406Sopenharmony_ci	  memcpy ((SANE_Word *) value, &gamma[0][0],
961141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
962141cc406Sopenharmony_ci	  break;
963141cc406Sopenharmony_ci	case opt_gamma_r:
964141cc406Sopenharmony_ci	  memcpy ((SANE_Word *) value, &gamma[1][0],
965141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
966141cc406Sopenharmony_ci	  break;
967141cc406Sopenharmony_ci	case opt_gamma_g:
968141cc406Sopenharmony_ci	  memcpy ((SANE_Word *) value, &gamma[2][0],
969141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
970141cc406Sopenharmony_ci	  break;
971141cc406Sopenharmony_ci	case opt_gamma_b:
972141cc406Sopenharmony_ci	  memcpy ((SANE_Word *) value, &gamma[3][0],
973141cc406Sopenharmony_ci		  256 * sizeof (SANE_Word));
974141cc406Sopenharmony_ci	  break;
975141cc406Sopenharmony_ci	case opt_status:
976141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_none;
977141cc406Sopenharmony_ci	  break;
978141cc406Sopenharmony_ci	case opt_status_eof:
979141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_eof;
980141cc406Sopenharmony_ci	  break;
981141cc406Sopenharmony_ci	case opt_status_jammed:
982141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_jammed;
983141cc406Sopenharmony_ci	  break;
984141cc406Sopenharmony_ci	case opt_status_nodocs:
985141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_nodocs;
986141cc406Sopenharmony_ci	  break;
987141cc406Sopenharmony_ci	case opt_status_coveropen:
988141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_coveropen;
989141cc406Sopenharmony_ci	  break;
990141cc406Sopenharmony_ci	case opt_status_ioerror:
991141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_ioerror;
992141cc406Sopenharmony_ci	  break;
993141cc406Sopenharmony_ci	case opt_status_nomem:
994141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_nomem;
995141cc406Sopenharmony_ci	  break;
996141cc406Sopenharmony_ci	case opt_status_accessdenied:
997141cc406Sopenharmony_ci	  *(SANE_Word *) value = status_accessdenied;
998141cc406Sopenharmony_ci	  break;
999141cc406Sopenharmony_ci	default:
1000141cc406Sopenharmony_ci	  return SANE_STATUS_INVAL;
1001141cc406Sopenharmony_ci	}
1002141cc406Sopenharmony_ci      break;
1003141cc406Sopenharmony_ci    }
1004141cc406Sopenharmony_ci  if (info)
1005141cc406Sopenharmony_ci    *info = myinfo;
1006141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1007141cc406Sopenharmony_ci}
1008141cc406Sopenharmony_ci
1009141cc406Sopenharmony_cistatic void
1010141cc406Sopenharmony_ciget_line (char *buf, int len, FILE * f)
1011141cc406Sopenharmony_ci{
1012141cc406Sopenharmony_ci  do
1013141cc406Sopenharmony_ci    fgets (buf, len, f);
1014141cc406Sopenharmony_ci  while (*buf == '#');
1015141cc406Sopenharmony_ci}
1016141cc406Sopenharmony_ci
1017141cc406Sopenharmony_cistatic int
1018141cc406Sopenharmony_cigetparmfromfile (void)
1019141cc406Sopenharmony_ci{
1020141cc406Sopenharmony_ci  FILE *fn;
1021141cc406Sopenharmony_ci  int x, y;
1022141cc406Sopenharmony_ci  char buf[1024];
1023141cc406Sopenharmony_ci
1024141cc406Sopenharmony_ci  parms.depth = 8;
1025141cc406Sopenharmony_ci  parms.bytes_per_line = parms.pixels_per_line = parms.lines = 0;
1026141cc406Sopenharmony_ci  if ((fn = fopen (filename, "rb")) == NULL)
1027141cc406Sopenharmony_ci    {
1028141cc406Sopenharmony_ci      DBG (1, "getparmfromfile: unable to open file \"%s\"\n", filename);
1029141cc406Sopenharmony_ci      return -1;
1030141cc406Sopenharmony_ci    }
1031141cc406Sopenharmony_ci
1032141cc406Sopenharmony_ci  /* Skip comments. */
1033141cc406Sopenharmony_ci  do
1034141cc406Sopenharmony_ci    get_line (buf, sizeof (buf), fn);
1035141cc406Sopenharmony_ci  while (*buf == '#');
1036141cc406Sopenharmony_ci  if (!strncmp (buf, "P4", 2))
1037141cc406Sopenharmony_ci    {
1038141cc406Sopenharmony_ci      /* Binary monochrome. */
1039141cc406Sopenharmony_ci      parms.depth = 1;
1040141cc406Sopenharmony_ci      ppm_type = ppm_bitmap;
1041141cc406Sopenharmony_ci    }
1042141cc406Sopenharmony_ci  else if (!strncmp (buf, "P5", 2))
1043141cc406Sopenharmony_ci    {
1044141cc406Sopenharmony_ci      /* Grayscale. */
1045141cc406Sopenharmony_ci      parms.depth = 8;
1046141cc406Sopenharmony_ci      ppm_type = ppm_greyscale;
1047141cc406Sopenharmony_ci    }
1048141cc406Sopenharmony_ci  else if (!strncmp (buf, "P6", 2))
1049141cc406Sopenharmony_ci    {
1050141cc406Sopenharmony_ci      /* Color. */
1051141cc406Sopenharmony_ci      parms.depth = 8;
1052141cc406Sopenharmony_ci      ppm_type = ppm_color;
1053141cc406Sopenharmony_ci    }
1054141cc406Sopenharmony_ci  else
1055141cc406Sopenharmony_ci    {
1056141cc406Sopenharmony_ci      DBG (1, "getparmfromfile: %s is not a recognized PPM\n", filename);
1057141cc406Sopenharmony_ci      fclose (fn);
1058141cc406Sopenharmony_ci      return -1;
1059141cc406Sopenharmony_ci    }
1060141cc406Sopenharmony_ci
1061141cc406Sopenharmony_ci  /* Skip comments. */
1062141cc406Sopenharmony_ci  do
1063141cc406Sopenharmony_ci    get_line (buf, sizeof (buf), fn);
1064141cc406Sopenharmony_ci  while (*buf == '#');
1065141cc406Sopenharmony_ci  sscanf (buf, "%d %d", &x, &y);
1066141cc406Sopenharmony_ci
1067141cc406Sopenharmony_ci  parms.last_frame = SANE_TRUE;
1068141cc406Sopenharmony_ci  parms.bytes_per_line = (ppm_type == ppm_bitmap) ? (x + 7) / 8 : x;
1069141cc406Sopenharmony_ci  parms.pixels_per_line = x;
1070141cc406Sopenharmony_ci  if (hand_scanner)
1071141cc406Sopenharmony_ci    parms.lines = -1;
1072141cc406Sopenharmony_ci  else
1073141cc406Sopenharmony_ci    parms.lines = y;
1074141cc406Sopenharmony_ci  if ((ppm_type == ppm_greyscale) || (ppm_type == ppm_bitmap) || gray)
1075141cc406Sopenharmony_ci    parms.format = SANE_FRAME_GRAY;
1076141cc406Sopenharmony_ci  else
1077141cc406Sopenharmony_ci    {
1078141cc406Sopenharmony_ci      if (three_pass)
1079141cc406Sopenharmony_ci	{
1080141cc406Sopenharmony_ci	  parms.format = SANE_FRAME_RED + (pass + 1) % 3;
1081141cc406Sopenharmony_ci	  parms.last_frame = (pass >= 2);
1082141cc406Sopenharmony_ci	}
1083141cc406Sopenharmony_ci      else
1084141cc406Sopenharmony_ci	{
1085141cc406Sopenharmony_ci	  parms.format = SANE_FRAME_RGB;
1086141cc406Sopenharmony_ci	  parms.bytes_per_line *= 3;
1087141cc406Sopenharmony_ci	}
1088141cc406Sopenharmony_ci    }
1089141cc406Sopenharmony_ci  fclose (fn);
1090141cc406Sopenharmony_ci  return 0;
1091141cc406Sopenharmony_ci}
1092141cc406Sopenharmony_ci
1093141cc406Sopenharmony_ciSANE_Status
1094141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1095141cc406Sopenharmony_ci{
1096141cc406Sopenharmony_ci  int rc = SANE_STATUS_GOOD;
1097141cc406Sopenharmony_ci
1098141cc406Sopenharmony_ci  DBG (2, "sane_get_parameters\n");
1099141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1100141cc406Sopenharmony_ci    rc = SANE_STATUS_INVAL;	/* Unknown handle ... */
1101141cc406Sopenharmony_ci  else if (getparmfromfile ())
1102141cc406Sopenharmony_ci    rc = SANE_STATUS_INVAL;
1103141cc406Sopenharmony_ci  *params = parms;
1104141cc406Sopenharmony_ci  return rc;
1105141cc406Sopenharmony_ci}
1106141cc406Sopenharmony_ci
1107141cc406Sopenharmony_ciSANE_Status
1108141cc406Sopenharmony_cisane_start (SANE_Handle handle)
1109141cc406Sopenharmony_ci{
1110141cc406Sopenharmony_ci  char buf[1024];
1111141cc406Sopenharmony_ci  int nlines;
1112141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
1113141cc406Sopenharmony_ci  struct timeval current;
1114141cc406Sopenharmony_ci#endif
1115141cc406Sopenharmony_ci
1116141cc406Sopenharmony_ci  DBG (2, "sane_start\n");
1117141cc406Sopenharmony_ci  rgb_comp = 0;
1118141cc406Sopenharmony_ci  if (handle != MAGIC || !is_open)
1119141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;	/* Unknown handle ... */
1120141cc406Sopenharmony_ci
1121141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
1122141cc406Sopenharmony_ci  if(warming_up == SANE_TRUE)
1123141cc406Sopenharmony_ci   {
1124141cc406Sopenharmony_ci      gettimeofday(&current,NULL);
1125141cc406Sopenharmony_ci      if(current.tv_sec-start.tv_sec>5)
1126141cc406Sopenharmony_ci	{
1127141cc406Sopenharmony_ci	   start.tv_sec = current.tv_sec;
1128141cc406Sopenharmony_ci	   return SANE_STATUS_WARMING_UP;
1129141cc406Sopenharmony_ci	}
1130141cc406Sopenharmony_ci      if(current.tv_sec-start.tv_sec<5)
1131141cc406Sopenharmony_ci	return SANE_STATUS_WARMING_UP;
1132141cc406Sopenharmony_ci   }
1133141cc406Sopenharmony_ci#endif
1134141cc406Sopenharmony_ci
1135141cc406Sopenharmony_ci  if (infile != NULL)
1136141cc406Sopenharmony_ci    {
1137141cc406Sopenharmony_ci      fclose (infile);
1138141cc406Sopenharmony_ci      infile = NULL;
1139141cc406Sopenharmony_ci      if (!three_pass || ++pass >= 3)
1140141cc406Sopenharmony_ci	return SANE_STATUS_EOF;
1141141cc406Sopenharmony_ci    }
1142141cc406Sopenharmony_ci
1143141cc406Sopenharmony_ci  if (getparmfromfile ())
1144141cc406Sopenharmony_ci    return SANE_STATUS_INVAL;
1145141cc406Sopenharmony_ci
1146141cc406Sopenharmony_ci  if ((infile = fopen (filename, "rb")) == NULL)
1147141cc406Sopenharmony_ci    {
1148141cc406Sopenharmony_ci      DBG (1, "sane_start: unable to open file \"%s\"\n", filename);
1149141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1150141cc406Sopenharmony_ci    }
1151141cc406Sopenharmony_ci
1152141cc406Sopenharmony_ci  /* Skip the header (only two lines for a bitmap). */
1153141cc406Sopenharmony_ci  nlines = (ppm_type == ppm_bitmap) ? 1 : 0;
1154141cc406Sopenharmony_ci  while (nlines < 3)
1155141cc406Sopenharmony_ci    {
1156141cc406Sopenharmony_ci      /* Skip comments. */
1157141cc406Sopenharmony_ci      get_line (buf, sizeof (buf), infile);
1158141cc406Sopenharmony_ci      if (*buf != '#')
1159141cc406Sopenharmony_ci	nlines++;
1160141cc406Sopenharmony_ci    }
1161141cc406Sopenharmony_ci
1162141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1163141cc406Sopenharmony_ci}
1164141cc406Sopenharmony_ci
1165141cc406Sopenharmony_cistatic SANE_Int rgblength = 0;
1166141cc406Sopenharmony_cistatic SANE_Byte *rgbbuf = 0;
1167141cc406Sopenharmony_cistatic SANE_Byte rgbleftover[3] = { 0, 0, 0 };
1168141cc406Sopenharmony_ci
1169141cc406Sopenharmony_ciSANE_Status
1170141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte * data,
1171141cc406Sopenharmony_ci	   SANE_Int max_length, SANE_Int * length)
1172141cc406Sopenharmony_ci{
1173141cc406Sopenharmony_ci  int len, x, hlp;
1174141cc406Sopenharmony_ci
1175141cc406Sopenharmony_ci  DBG (2, "sane_read: max_length = %d, rgbleftover = {%d, %d, %d}\n",
1176141cc406Sopenharmony_ci       max_length, rgbleftover[0], rgbleftover[1], rgbleftover[2]);
1177141cc406Sopenharmony_ci  if (!length)
1178141cc406Sopenharmony_ci    {
1179141cc406Sopenharmony_ci      DBG (1, "sane_read: length == NULL\n");
1180141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1181141cc406Sopenharmony_ci    }
1182141cc406Sopenharmony_ci  *length = 0;
1183141cc406Sopenharmony_ci  if (!data)
1184141cc406Sopenharmony_ci    {
1185141cc406Sopenharmony_ci      DBG (1, "sane_read: data == NULL\n");
1186141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1187141cc406Sopenharmony_ci    }
1188141cc406Sopenharmony_ci  if (handle != MAGIC)
1189141cc406Sopenharmony_ci    {
1190141cc406Sopenharmony_ci      DBG (1, "sane_read: unknown handle\n");
1191141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1192141cc406Sopenharmony_ci    }
1193141cc406Sopenharmony_ci  if (!is_open)
1194141cc406Sopenharmony_ci    {
1195141cc406Sopenharmony_ci      DBG (1, "sane_read: call sane_open first\n");
1196141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1197141cc406Sopenharmony_ci    }
1198141cc406Sopenharmony_ci  if (!infile)
1199141cc406Sopenharmony_ci    {
1200141cc406Sopenharmony_ci      DBG (1, "sane_read: scan was cancelled\n");
1201141cc406Sopenharmony_ci      return SANE_STATUS_CANCELLED;
1202141cc406Sopenharmony_ci    }
1203141cc406Sopenharmony_ci  if (feof (infile))
1204141cc406Sopenharmony_ci    {
1205141cc406Sopenharmony_ci      DBG (2, "sane_read: EOF reached\n");
1206141cc406Sopenharmony_ci      return SANE_STATUS_EOF;
1207141cc406Sopenharmony_ci    }
1208141cc406Sopenharmony_ci
1209141cc406Sopenharmony_ci  if (status_jammed == SANE_TRUE)
1210141cc406Sopenharmony_ci    return SANE_STATUS_JAMMED;
1211141cc406Sopenharmony_ci  if (status_eof == SANE_TRUE)
1212141cc406Sopenharmony_ci    return SANE_STATUS_EOF;
1213141cc406Sopenharmony_ci  if (status_nodocs == SANE_TRUE)
1214141cc406Sopenharmony_ci    return SANE_STATUS_NO_DOCS;
1215141cc406Sopenharmony_ci  if (status_coveropen == SANE_TRUE)
1216141cc406Sopenharmony_ci    return SANE_STATUS_COVER_OPEN;
1217141cc406Sopenharmony_ci  if (status_ioerror == SANE_TRUE)
1218141cc406Sopenharmony_ci    return SANE_STATUS_IO_ERROR;
1219141cc406Sopenharmony_ci  if (status_nomem == SANE_TRUE)
1220141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
1221141cc406Sopenharmony_ci  if (status_accessdenied == SANE_TRUE)
1222141cc406Sopenharmony_ci    return SANE_STATUS_ACCESS_DENIED;
1223141cc406Sopenharmony_ci
1224141cc406Sopenharmony_ci  /* Allocate a buffer for the RGB values. */
1225141cc406Sopenharmony_ci  if (ppm_type == ppm_color && (gray || three_pass))
1226141cc406Sopenharmony_ci    {
1227141cc406Sopenharmony_ci      SANE_Byte *p, *q, *rgbend;
1228141cc406Sopenharmony_ci      if (rgbbuf == 0 || rgblength < 3 * max_length)
1229141cc406Sopenharmony_ci	{
1230141cc406Sopenharmony_ci	  /* Allocate a new rgbbuf. */
1231141cc406Sopenharmony_ci	  free (rgbbuf);
1232141cc406Sopenharmony_ci	  rgblength = 3 * max_length;
1233141cc406Sopenharmony_ci	  rgbbuf = malloc (rgblength);
1234141cc406Sopenharmony_ci	  if (rgbbuf == 0)
1235141cc406Sopenharmony_ci	    return SANE_STATUS_NO_MEM;
1236141cc406Sopenharmony_ci	}
1237141cc406Sopenharmony_ci      else
1238141cc406Sopenharmony_ci	rgblength = 3 * max_length;
1239141cc406Sopenharmony_ci
1240141cc406Sopenharmony_ci      /* Copy any leftovers into the buffer. */
1241141cc406Sopenharmony_ci      q = rgbbuf;
1242141cc406Sopenharmony_ci      p = rgbleftover + 1;
1243141cc406Sopenharmony_ci      while (p - rgbleftover <= rgbleftover[0])
1244141cc406Sopenharmony_ci	*q++ = *p++;
1245141cc406Sopenharmony_ci
1246141cc406Sopenharmony_ci      /* Slurp in the RGB buffer. */
1247141cc406Sopenharmony_ci      len = fread (q, 1, rgblength - rgbleftover[0], infile);
1248141cc406Sopenharmony_ci      rgbend = rgbbuf + len;
1249141cc406Sopenharmony_ci
1250141cc406Sopenharmony_ci      q = data;
1251141cc406Sopenharmony_ci      if (gray)
1252141cc406Sopenharmony_ci	{
1253141cc406Sopenharmony_ci	  /* Zip through the buffer, converting color data to grayscale. */
1254141cc406Sopenharmony_ci	  for (p = rgbbuf; p < rgbend; p += 3)
1255141cc406Sopenharmony_ci	    *q++ = ((long) p[0] + p[1] + p[2]) / 3;
1256141cc406Sopenharmony_ci	}
1257141cc406Sopenharmony_ci      else
1258141cc406Sopenharmony_ci	{
1259141cc406Sopenharmony_ci	  /* Zip through the buffer, extracting data for this pass. */
1260141cc406Sopenharmony_ci	  for (p = (rgbbuf + (pass + 1) % 3); p < rgbend; p += 3)
1261141cc406Sopenharmony_ci	    *q++ = *p;
1262141cc406Sopenharmony_ci	}
1263141cc406Sopenharmony_ci
1264141cc406Sopenharmony_ci      /* Save any leftovers in the array. */
1265141cc406Sopenharmony_ci      rgbleftover[0] = len % 3;
1266141cc406Sopenharmony_ci      p = rgbbuf + (len - rgbleftover[0]);
1267141cc406Sopenharmony_ci      q = rgbleftover + 1;
1268141cc406Sopenharmony_ci      while (p < rgbend)
1269141cc406Sopenharmony_ci	*q++ = *p++;
1270141cc406Sopenharmony_ci
1271141cc406Sopenharmony_ci      len /= 3;
1272141cc406Sopenharmony_ci    }
1273141cc406Sopenharmony_ci  else
1274141cc406Sopenharmony_ci    /* Suck in as much of the file as possible, since it's already in the
1275141cc406Sopenharmony_ci       correct format. */
1276141cc406Sopenharmony_ci    len = fread (data, 1, max_length, infile);
1277141cc406Sopenharmony_ci
1278141cc406Sopenharmony_ci  if (len == 0)
1279141cc406Sopenharmony_ci    {
1280141cc406Sopenharmony_ci      if (feof (infile))
1281141cc406Sopenharmony_ci	{
1282141cc406Sopenharmony_ci	  DBG (2, "sane_read: EOF reached\n");
1283141cc406Sopenharmony_ci	  return SANE_STATUS_EOF;
1284141cc406Sopenharmony_ci	}
1285141cc406Sopenharmony_ci      else
1286141cc406Sopenharmony_ci	{
1287141cc406Sopenharmony_ci	  DBG (1, "sane_read: error while reading file (%s)\n",
1288141cc406Sopenharmony_ci	       strerror (errno));
1289141cc406Sopenharmony_ci	  return SANE_STATUS_IO_ERROR;
1290141cc406Sopenharmony_ci	}
1291141cc406Sopenharmony_ci    }
1292141cc406Sopenharmony_ci
1293141cc406Sopenharmony_ci  if (parms.depth == 8)
1294141cc406Sopenharmony_ci    {
1295141cc406Sopenharmony_ci      /* Do the transformations ... DEMO ONLY ! THIS MAKES NO SENSE ! */
1296141cc406Sopenharmony_ci      for (x = 0; x < len; x++)
1297141cc406Sopenharmony_ci	{
1298141cc406Sopenharmony_ci	  hlp = *((unsigned char *) data + x) - 128;
1299141cc406Sopenharmony_ci	  hlp *= (contr + (100 << SANE_FIXED_SCALE_SHIFT));
1300141cc406Sopenharmony_ci	  hlp /= 100 << SANE_FIXED_SCALE_SHIFT;
1301141cc406Sopenharmony_ci	  hlp += (bright >> SANE_FIXED_SCALE_SHIFT) + 128;
1302141cc406Sopenharmony_ci	  if (hlp < 0)
1303141cc406Sopenharmony_ci	    hlp = 0;
1304141cc406Sopenharmony_ci	  if (hlp > 255)
1305141cc406Sopenharmony_ci	    hlp = 255;
1306141cc406Sopenharmony_ci	  *(data + x) = hlp;
1307141cc406Sopenharmony_ci	}
1308141cc406Sopenharmony_ci      /*gamma */
1309141cc406Sopenharmony_ci      if (usegamma)
1310141cc406Sopenharmony_ci	{
1311141cc406Sopenharmony_ci	  unsigned char uc;
1312141cc406Sopenharmony_ci	  if (gray)
1313141cc406Sopenharmony_ci	    {
1314141cc406Sopenharmony_ci	      for (x = 0; x < len; x++)
1315141cc406Sopenharmony_ci		{
1316141cc406Sopenharmony_ci		  uc = *((unsigned char *) data + x);
1317141cc406Sopenharmony_ci		  uc = gamma[0][uc];
1318141cc406Sopenharmony_ci		  *(data + x) = uc;
1319141cc406Sopenharmony_ci		}
1320141cc406Sopenharmony_ci	    }
1321141cc406Sopenharmony_ci	  else
1322141cc406Sopenharmony_ci	    {
1323141cc406Sopenharmony_ci	      for (x = 0; x < len; x++)
1324141cc406Sopenharmony_ci		{
1325141cc406Sopenharmony_ci		  if (parms.format == SANE_FRAME_RGB)
1326141cc406Sopenharmony_ci		    {
1327141cc406Sopenharmony_ci		      uc = *((unsigned char *) (data + x));
1328141cc406Sopenharmony_ci		      uc = (unsigned char) gamma[rgb_comp + 1][(int) uc];
1329141cc406Sopenharmony_ci		      *((unsigned char *) data + x) = uc;
1330141cc406Sopenharmony_ci		      rgb_comp += 1;
1331141cc406Sopenharmony_ci		      if (rgb_comp > 2)
1332141cc406Sopenharmony_ci			rgb_comp = 0;
1333141cc406Sopenharmony_ci		    }
1334141cc406Sopenharmony_ci		  else
1335141cc406Sopenharmony_ci		    {
1336141cc406Sopenharmony_ci		      int f = 0;
1337141cc406Sopenharmony_ci		      if (parms.format == SANE_FRAME_RED)
1338141cc406Sopenharmony_ci			f = 1;
1339141cc406Sopenharmony_ci		      if (parms.format == SANE_FRAME_GREEN)
1340141cc406Sopenharmony_ci			f = 2;
1341141cc406Sopenharmony_ci		      if (parms.format == SANE_FRAME_BLUE)
1342141cc406Sopenharmony_ci			f = 3;
1343141cc406Sopenharmony_ci		      if (f)
1344141cc406Sopenharmony_ci			{
1345141cc406Sopenharmony_ci			  uc = *((unsigned char *) (data + x));
1346141cc406Sopenharmony_ci			  uc = (unsigned char) gamma[f][(int) uc];
1347141cc406Sopenharmony_ci			  *((unsigned char *) data + x) = uc;
1348141cc406Sopenharmony_ci			}
1349141cc406Sopenharmony_ci		    }
1350141cc406Sopenharmony_ci		}
1351141cc406Sopenharmony_ci	    }
1352141cc406Sopenharmony_ci	}
1353141cc406Sopenharmony_ci    }
1354141cc406Sopenharmony_ci  *length = len;
1355141cc406Sopenharmony_ci  DBG (2, "sane_read: read %d bytes\n", len);
1356141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1357141cc406Sopenharmony_ci}
1358141cc406Sopenharmony_ci
1359141cc406Sopenharmony_civoid
1360141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
1361141cc406Sopenharmony_ci{
1362141cc406Sopenharmony_ci  DBG (2, "sane_cancel: handle = %p\n", handle);
1363141cc406Sopenharmony_ci  pass = 0;
1364141cc406Sopenharmony_ci  if (infile != NULL)
1365141cc406Sopenharmony_ci    {
1366141cc406Sopenharmony_ci      fclose (infile);
1367141cc406Sopenharmony_ci      infile = NULL;
1368141cc406Sopenharmony_ci    }
1369141cc406Sopenharmony_ci  return;
1370141cc406Sopenharmony_ci}
1371141cc406Sopenharmony_ci
1372141cc406Sopenharmony_ciSANE_Status
1373141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1374141cc406Sopenharmony_ci{
1375141cc406Sopenharmony_ci  DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
1376141cc406Sopenharmony_ci       non_blocking);
1377141cc406Sopenharmony_ci  if (!infile)
1378141cc406Sopenharmony_ci    {
1379141cc406Sopenharmony_ci      DBG (1, "sane_set_io_mode: not scanning\n");
1380141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
1381141cc406Sopenharmony_ci    }
1382141cc406Sopenharmony_ci  if (non_blocking)
1383141cc406Sopenharmony_ci    return SANE_STATUS_UNSUPPORTED;
1384141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1385141cc406Sopenharmony_ci}
1386141cc406Sopenharmony_ci
1387141cc406Sopenharmony_ciSANE_Status
1388141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1389141cc406Sopenharmony_ci{
1390141cc406Sopenharmony_ci  DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
1391141cc406Sopenharmony_ci       fd ? "!=" : "=");
1392141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
1393141cc406Sopenharmony_ci}
1394