1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 1998, 1999
4141cc406Sopenharmony_ci   Kazuya Fukuda, Abel Deuring based on BYTEC GmbH Germany
5141cc406Sopenharmony_ci   Written by Helmut Koeberle previous Work on canon.c file from the
6141cc406Sopenharmony_ci   SANE package.
7141cc406Sopenharmony_ci
8141cc406Sopenharmony_ci   This file is part of the SANE package.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
11141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
12141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
13141cc406Sopenharmony_ci   License, or (at your option) any later version.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
16141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
17141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18141cc406Sopenharmony_ci   General Public License for more details.
19141cc406Sopenharmony_ci
20141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
21141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
22141cc406Sopenharmony_ci
23141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
24141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
25141cc406Sopenharmony_ci
26141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
27141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
28141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
30141cc406Sopenharmony_ci   account of linking the SANE library code into it.
31141cc406Sopenharmony_ci
32141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
33141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
34141cc406Sopenharmony_ci   License.
35141cc406Sopenharmony_ci
36141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
37141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
38141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
41141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
42141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci   This file implements a SANE backend for Sharp flatbed scanners.  */
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci/*
47141cc406Sopenharmony_ci   Version 0.32
48141cc406Sopenharmony_ci   changes to version 0.31:
49141cc406Sopenharmony_ci   - support for JX320 added (Thanks to Isaac Wilcox for providind the
50141cc406Sopenharmony_ci     patch)
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci   Version 0.31
53141cc406Sopenharmony_ci   changes to version 0.30:
54141cc406Sopenharmony_ci   - support for JX350 added (Thanks to Shuhei Tomita for providind the
55141cc406Sopenharmony_ci     patch)
56141cc406Sopenharmony_ci
57141cc406Sopenharmony_ci   changes to version 0.20
58141cc406Sopenharmony_ci   - support for the proposed extended open function in sanei_scsi.c added
59141cc406Sopenharmony_ci   - support for ADF and FSU (transparency adapter) added
60141cc406Sopenharmony_ci   - simple sense handler added
61141cc406Sopenharmony_ci   - preview added
62141cc406Sopenharmony_ci   - added several missing statements "s->fd = -1;" after
63141cc406Sopenharmony_ci     "sanei_scsi_close(s->fd)" to error returns in sane_start();
64141cc406Sopenharmony_ci   - maximum scan sizes are read from the scanner, if a JX330 or JX250
65141cc406Sopenharmony_ci     is used. (this avoids the guessing of scan sizes for the JX330)
66141cc406Sopenharmony_ci   - gamma table support added
67141cc406Sopenharmony_ci   - "Fixed gamma selection (1.0/2.2)", available for JX330 and JX610,
68141cc406Sopenharmony_ci     is now implemented for the JX250 by downloading a gamma table
69141cc406Sopenharmony_ci   - changed the calls to free() and strdup() in sane_control_option to
70141cc406Sopenharmony_ci     strcpy.
71141cc406Sopenharmony_ci     (I don't like too frequent unchecked malloc()s and strdups :) Abel)
72141cc406Sopenharmony_ci   - cleaned up some quirks in option handling, eg, that "threshold"
73141cc406Sopenharmony_ci     was initially enabled, while the initial scan mode is "color"
74141cc406Sopenharmony_ci   - cleaned up setting SANE_INFO_RELOAD_OPTIONS and SANE_INFO_RELOAD_PARAMS
75141cc406Sopenharmony_ci     bits in sane_control_option
76141cc406Sopenharmony_ci   - bi-level color scans now give useful (8 bit) output
77141cc406Sopenharmony_ci   - separate thresholds for red, green, blue (bi-level color scan) added
78141cc406Sopenharmony_ci*/
79141cc406Sopenharmony_ci#include "../include/sane/config.h"
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_ci#include <limits.h>
82141cc406Sopenharmony_ci#include <stdlib.h>
83141cc406Sopenharmony_ci#include <stdarg.h>
84141cc406Sopenharmony_ci#include <string.h>
85141cc406Sopenharmony_ci#include <unistd.h>
86141cc406Sopenharmony_ci#include <errno.h>
87141cc406Sopenharmony_ci#include <math.h>
88141cc406Sopenharmony_ci
89141cc406Sopenharmony_ci#include "../include/sane/sane.h"
90141cc406Sopenharmony_ci#include "../include/sane/saneopts.h"
91141cc406Sopenharmony_ci#include "../include/sane/sanei_scsi.h"
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_ci/* QUEUEDEBUG should be undefined unless you want to play
94141cc406Sopenharmony_ci   with the sanei_scsi.c under Linux and/or with the Linux's SG driver,
95141cc406Sopenharmony_ci   or your suspect problems with command queueing
96141cc406Sopenharmony_ci*/
97141cc406Sopenharmony_ci#if 0
98141cc406Sopenharmony_ci#define QUEUEDEBUG
99141cc406Sopenharmony_ci#define DEBUG
100141cc406Sopenharmony_ci#ifdef DEBUG
101141cc406Sopenharmony_ci#include <unistd.h>
102141cc406Sopenharmony_ci#include <sys/time.h>
103141cc406Sopenharmony_ci#endif
104141cc406Sopenharmony_ci#endif
105141cc406Sopenharmony_ci
106141cc406Sopenharmony_ci/* USE_FORK: fork a special reader process
107141cc406Sopenharmony_ci*/
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci#ifdef HAVE_SYS_SHM_H
110141cc406Sopenharmony_ci#ifndef HAVE_OS2_H
111141cc406Sopenharmony_ci#define USE_FORK
112141cc406Sopenharmony_ci#endif
113141cc406Sopenharmony_ci#endif
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_ci#ifdef USE_FORK
116141cc406Sopenharmony_ci#include <signal.h>
117141cc406Sopenharmony_ci#include <fcntl.h>
118141cc406Sopenharmony_ci#include <sys/types.h>
119141cc406Sopenharmony_ci#include <sys/wait.h>
120141cc406Sopenharmony_ci
121141cc406Sopenharmony_ci#include <sys/ipc.h>
122141cc406Sopenharmony_ci#include <sys/shm.h>
123141cc406Sopenharmony_ci
124141cc406Sopenharmony_ci#endif /* USE_FORK */
125141cc406Sopenharmony_ci
126141cc406Sopenharmony_ci/* xxx I'm not sure, if I understood the JX610 and JX330 manuals right,
127141cc406Sopenharmony_ci   that the data for the SEND command should be in ASCII format...
128141cc406Sopenharmony_ci   SEND commands with a data bock are used, if USE_CUSTOM_GAMMA
129141cc406Sopenharmony_ci   and / or USE_COLOR_THRESHOLD are enabled.
130141cc406Sopenharmony_ci   Abel
131141cc406Sopenharmony_ci*/
132141cc406Sopenharmony_ci#define USE_CUSTOM_GAMMA
133141cc406Sopenharmony_ci#define USE_COLOR_THRESHOLD
134141cc406Sopenharmony_ci/* enable a short list of some standard resolutions. XSane provides
135141cc406Sopenharmony_ci   its own resolution list; therefore its is generally not reasonable
136141cc406Sopenharmony_ci   to enable this list, if you mainly using XSane. But it might be handy
137141cc406Sopenharmony_ci   if you are working with xscanimage
138141cc406Sopenharmony_ci*/
139141cc406Sopenharmony_ci/* #define USE_RESOLUTION_LIST */
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_ci/* enable separate specification of resolution in X and Y direction.
142141cc406Sopenharmony_ci   XSane will show the Y-resolution at a quite different place than
143141cc406Sopenharmony_ci   the X-resolution
144141cc406Sopenharmony_ci*/
145141cc406Sopenharmony_ci/* #define USE_SEPARATE_Y_RESOLUTION */
146141cc406Sopenharmony_ci
147141cc406Sopenharmony_ci
148141cc406Sopenharmony_ci#define BACKEND_NAME sharp
149141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
150141cc406Sopenharmony_ci
151141cc406Sopenharmony_ci#include <sharp.h>
152141cc406Sopenharmony_ci
153141cc406Sopenharmony_ci#ifndef PATH_MAX
154141cc406Sopenharmony_ci#define PATH_MAX	1024
155141cc406Sopenharmony_ci#endif
156141cc406Sopenharmony_ci
157141cc406Sopenharmony_ci#define DEFAULT_MUD_JX610 25
158141cc406Sopenharmony_ci#define DEFAULT_MUD_JX320 25
159141cc406Sopenharmony_ci#define DEFAULT_MUD_JX330 1200
160141cc406Sopenharmony_ci#define DEFAULT_MUD_JX250 1200
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_ci#define PIX_TO_MM(x, mud) ((x) * 25.4 / mud)
163141cc406Sopenharmony_ci#define MM_TO_PIX(x, mud) ((x) * mud / 25.4)
164141cc406Sopenharmony_ci
165141cc406Sopenharmony_ci#include "../include/sane/sanei_config.h"
166141cc406Sopenharmony_ci#define SHARP_CONFIG_FILE "sharp.conf"
167141cc406Sopenharmony_ci
168141cc406Sopenharmony_cistatic int num_devices = 0;
169141cc406Sopenharmony_cistatic SHARP_Device *first_dev = NULL;
170141cc406Sopenharmony_cistatic SHARP_Scanner *first_handle = NULL;
171141cc406Sopenharmony_ci
172141cc406Sopenharmony_citypedef enum
173141cc406Sopenharmony_ci  {
174141cc406Sopenharmony_ci    MODES_LINEART  = 0,
175141cc406Sopenharmony_ci    MODES_GRAY,
176141cc406Sopenharmony_ci    MODES_LINEART_COLOR,
177141cc406Sopenharmony_ci    MODES_COLOR
178141cc406Sopenharmony_ci  }
179141cc406Sopenharmony_ciModes;
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci#define M_LINEART            SANE_VALUE_SCAN_MODE_LINEART
182141cc406Sopenharmony_ci#define M_GRAY               SANE_VALUE_SCAN_MODE_GRAY
183141cc406Sopenharmony_ci#define M_LINEART_COLOR      SANE_VALUE_SCAN_MODE_COLOR_LINEART
184141cc406Sopenharmony_ci#define M_COLOR              SANE_VALUE_SCAN_MODE_COLOR
185141cc406Sopenharmony_cistatic const SANE_String_Const mode_list[] =
186141cc406Sopenharmony_ci{
187141cc406Sopenharmony_ci  M_LINEART, M_GRAY, M_LINEART_COLOR, M_COLOR,
188141cc406Sopenharmony_ci  0
189141cc406Sopenharmony_ci};
190141cc406Sopenharmony_ci
191141cc406Sopenharmony_ci#define M_BILEVEL        "none"
192141cc406Sopenharmony_ci#define M_BAYER          "Dither Bayer"
193141cc406Sopenharmony_ci#define M_SPIRAL         "Dither Spiral"
194141cc406Sopenharmony_ci#define M_DISPERSED      "Dither Dispersed"
195141cc406Sopenharmony_ci#define M_ERRDIFFUSION   "Error Diffusion"
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_cistatic const SANE_String_Const halftone_list[] =
198141cc406Sopenharmony_ci{
199141cc406Sopenharmony_ci  M_BILEVEL, M_BAYER, M_SPIRAL, M_DISPERSED, M_ERRDIFFUSION,
200141cc406Sopenharmony_ci  0
201141cc406Sopenharmony_ci};
202141cc406Sopenharmony_ci
203141cc406Sopenharmony_ci#define LIGHT_GREEN "green"
204141cc406Sopenharmony_ci#define LIGHT_RED   "red"
205141cc406Sopenharmony_ci#define LIGHT_BLUE  "blue"
206141cc406Sopenharmony_ci#define LIGHT_WHITE "white"
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_ci#define MAX_RETRIES 50
209141cc406Sopenharmony_ci
210141cc406Sopenharmony_cistatic const SANE_String_Const light_color_list[] =
211141cc406Sopenharmony_ci{
212141cc406Sopenharmony_ci  LIGHT_GREEN, LIGHT_RED, LIGHT_BLUE, LIGHT_WHITE,
213141cc406Sopenharmony_ci  0
214141cc406Sopenharmony_ci};
215141cc406Sopenharmony_ci
216141cc406Sopenharmony_ci/* possible values for ADF/FSU selection */
217141cc406Sopenharmony_cistatic SANE_String use_adf = "Automatic Document Feeder";
218141cc406Sopenharmony_cistatic SANE_String use_fsu = "Transparency Adapter";
219141cc406Sopenharmony_cistatic SANE_String use_simple = "Flatbed";
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_ci/* auto selection of ADF and FSU, as described in the JX330 manual,
222141cc406Sopenharmony_ci   is a nice idea -- but I assume that the possible scan window
223141cc406Sopenharmony_ci   sizes depend not only for the JX250, but also for JX330 on the
224141cc406Sopenharmony_ci   usage of ADF or FSU. Thus, the user might be able to select scan
225141cc406Sopenharmony_ci   windows of an "illegal" size, which would have to be automatically
226141cc406Sopenharmony_ci   corrected, and I don't see, how the user could be informed about
227141cc406Sopenharmony_ci   this "window clipping". More important, I don't see, how the
228141cc406Sopenharmony_ci   frontend could be informed that the ADF is automatically enabled.
229141cc406Sopenharmony_ci
230141cc406Sopenharmony_ci   Insert a "#define ALLOW_AUTO_SELECT_ADF", if you want to play
231141cc406Sopenharmony_ci   with this feature.
232141cc406Sopenharmony_ci*/
233141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
234141cc406Sopenharmony_cistatic SANE_String_Const use_auto = "AutoSelection";
235141cc406Sopenharmony_ci#endif
236141cc406Sopenharmony_ci
237141cc406Sopenharmony_ci#define HAVE_FSU 1
238141cc406Sopenharmony_ci#define HAVE_ADF 2
239141cc406Sopenharmony_ci
240141cc406Sopenharmony_ci/* The follow #defines are used in SHARP_Scanner.adf_fsu_mode
241141cc406Sopenharmony_ci   and as indexes for the arrays x_ranges, y_ranges in SHARP_Device
242141cc406Sopenharmony_ci*/
243141cc406Sopenharmony_ci#define SCAN_SIMPLE 0
244141cc406Sopenharmony_ci#define SCAN_WITH_FSU 1
245141cc406Sopenharmony_ci#define SCAN_WITH_ADF 2
246141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
247141cc406Sopenharmony_ci#define SCAN_ADF_FSU_AUTO 3
248141cc406Sopenharmony_ci#endif
249141cc406Sopenharmony_ci#define LOAD_PAPER 1
250141cc406Sopenharmony_ci#define UNLOAD_PAPER 0
251141cc406Sopenharmony_ci
252141cc406Sopenharmony_ci#define PAPER_MAX  10
253141cc406Sopenharmony_ci#define W_LETTER "11\"x17\""
254141cc406Sopenharmony_ci#define INVOICE  "8.5\"x5.5\""
255141cc406Sopenharmony_cistatic const SANE_String_Const paper_list_jx610[] =
256141cc406Sopenharmony_ci{
257141cc406Sopenharmony_ci  "A3", "A4", "A5", "A6", "B4", "B5",
258141cc406Sopenharmony_ci  W_LETTER, "Legal", "Letter", INVOICE,
259141cc406Sopenharmony_ci  0
260141cc406Sopenharmony_ci};
261141cc406Sopenharmony_ci
262141cc406Sopenharmony_cistatic const SANE_String_Const paper_list_jx330[] =
263141cc406Sopenharmony_ci{
264141cc406Sopenharmony_ci  "A4", "A5", "A6", "B5",
265141cc406Sopenharmony_ci  0
266141cc406Sopenharmony_ci};
267141cc406Sopenharmony_ci
268141cc406Sopenharmony_ci#define GAMMA10    "1.0"
269141cc406Sopenharmony_ci#define GAMMA22    "2.2"
270141cc406Sopenharmony_ci
271141cc406Sopenharmony_cistatic const SANE_String_Const gamma_list[] =
272141cc406Sopenharmony_ci{
273141cc406Sopenharmony_ci  GAMMA10, GAMMA22,
274141cc406Sopenharmony_ci  0
275141cc406Sopenharmony_ci};
276141cc406Sopenharmony_ci
277141cc406Sopenharmony_ci#if 0
278141cc406Sopenharmony_ci#define SPEED_NORMAL    "Normal"
279141cc406Sopenharmony_ci#define SPEED_FAST      "Fast"
280141cc406Sopenharmony_cistatic const SANE_String_Const speed_list[] =
281141cc406Sopenharmony_ci{
282141cc406Sopenharmony_ci  SPEED_NORMAL, SPEED_FAST,
283141cc406Sopenharmony_ci  0
284141cc406Sopenharmony_ci};
285141cc406Sopenharmony_ci#endif
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST
288141cc406Sopenharmony_ci#define RESOLUTION_MAX_JX610 8
289141cc406Sopenharmony_cistatic const SANE_String_Const resolution_list_jx610[] =
290141cc406Sopenharmony_ci{
291141cc406Sopenharmony_ci  "50", "75", "100", "150", "200", "300", "400", "600", "Select",
292141cc406Sopenharmony_ci  0
293141cc406Sopenharmony_ci};
294141cc406Sopenharmony_ci
295141cc406Sopenharmony_ci#define RESOLUTION_MAX_JX250 7
296141cc406Sopenharmony_cistatic const SANE_String_Const resolution_list_jx250[] =
297141cc406Sopenharmony_ci{
298141cc406Sopenharmony_ci  "50", "75", "100", "150", "200", "300", "400", "Select",
299141cc406Sopenharmony_ci  0
300141cc406Sopenharmony_ci};
301141cc406Sopenharmony_ci#endif
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ci#define EDGE_NONE    "None"
304141cc406Sopenharmony_ci#define EDGE_MIDDLE  "Middle"
305141cc406Sopenharmony_ci#define EDGE_STRONG  "Strong"
306141cc406Sopenharmony_ci#define EDGE_BLUR    "Blur"
307141cc406Sopenharmony_cistatic const SANE_String_Const edge_emphasis_list[] =
308141cc406Sopenharmony_ci{
309141cc406Sopenharmony_ci  EDGE_NONE, EDGE_MIDDLE, EDGE_STRONG, EDGE_BLUR,
310141cc406Sopenharmony_ci  0
311141cc406Sopenharmony_ci};
312141cc406Sopenharmony_ci
313141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
314141cc406Sopenharmony_cistatic const SANE_Range u8_range =
315141cc406Sopenharmony_ci  {
316141cc406Sopenharmony_ci      0,				/* minimum */
317141cc406Sopenharmony_ci    255,				/* maximum */
318141cc406Sopenharmony_ci      0				/* quantization */
319141cc406Sopenharmony_ci  };
320141cc406Sopenharmony_ci#endif
321141cc406Sopenharmony_ci
322141cc406Sopenharmony_cistatic SANE_Status
323141cc406Sopenharmony_cisense_handler(int __sane_unused__ fd, u_char *sense_buffer, void *s)
324141cc406Sopenharmony_ci{
325141cc406Sopenharmony_ci  int sense_key;
326141cc406Sopenharmony_ci  SHARP_Sense_Data *sdat = (SHARP_Sense_Data *) s;
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci#define add_sense_code sense_buffer[12]
329141cc406Sopenharmony_ci#define add_sense_qual sense_buffer[13]
330141cc406Sopenharmony_ci
331141cc406Sopenharmony_ci  memcpy(sdat->sb, sense_buffer, 16);
332141cc406Sopenharmony_ci
333141cc406Sopenharmony_ci  DBG(10, "sense code: %02x %02x %02x %02x %02x %02x %02x %02x "
334141cc406Sopenharmony_ci          "%02x %02x %02x %02x %02x %02x %02x %02x\n",
335141cc406Sopenharmony_ci          sense_buffer[0], sense_buffer[1], sense_buffer[2], sense_buffer[3],
336141cc406Sopenharmony_ci          sense_buffer[4], sense_buffer[5], sense_buffer[6], sense_buffer[7],
337141cc406Sopenharmony_ci          sense_buffer[8], sense_buffer[9], sense_buffer[10], sense_buffer[11],
338141cc406Sopenharmony_ci          sense_buffer[12], sense_buffer[13], sense_buffer[14], sense_buffer[15]);
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci  sense_key = sense_buffer[2] & 0x0F;
341141cc406Sopenharmony_ci  /* do we have additional information ? */
342141cc406Sopenharmony_ci  if (sense_buffer[7] >= 5)
343141cc406Sopenharmony_ci    {
344141cc406Sopenharmony_ci      if (sdat->model == JX610)
345141cc406Sopenharmony_ci        {
346141cc406Sopenharmony_ci          /* The JX610 uses somewhat different error codes */
347141cc406Sopenharmony_ci          switch (add_sense_code)
348141cc406Sopenharmony_ci            {
349141cc406Sopenharmony_ci              case 0x04:
350141cc406Sopenharmony_ci                DBG(5, "error: scanner not ready\n");
351141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
352141cc406Sopenharmony_ci              case 0x08:
353141cc406Sopenharmony_ci                DBG(5, "error: scanner communication failure (time out?)\n");
354141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
355141cc406Sopenharmony_ci              case 0x1A:
356141cc406Sopenharmony_ci                DBG(10, "error: parameter list length error\n");
357141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
358141cc406Sopenharmony_ci              case 0x20:
359141cc406Sopenharmony_ci                DBG(10, "error: invalid command code\n");
360141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
361141cc406Sopenharmony_ci              case 0x24:
362141cc406Sopenharmony_ci                DBG(10, "error: invalid field in CDB\n");
363141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
364141cc406Sopenharmony_ci              case 0x25:
365141cc406Sopenharmony_ci                DBG(10, "error: LUN not supported\n");
366141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
367141cc406Sopenharmony_ci              case 0x26:
368141cc406Sopenharmony_ci                DBG(10, "error: invalid field in parameter list\n");
369141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
370141cc406Sopenharmony_ci              case 0x29:
371141cc406Sopenharmony_ci                DBG(10, "note: reset occurred\n");
372141cc406Sopenharmony_ci                return SANE_STATUS_GOOD;
373141cc406Sopenharmony_ci              case 0x2a:
374141cc406Sopenharmony_ci                DBG(10, "note: mode parameter change\n");
375141cc406Sopenharmony_ci                return SANE_STATUS_GOOD;
376141cc406Sopenharmony_ci              case 0x37:
377141cc406Sopenharmony_ci                DBG(10, "note: rounded parameter\n");
378141cc406Sopenharmony_ci                return SANE_STATUS_GOOD;
379141cc406Sopenharmony_ci              case 0x39:
380141cc406Sopenharmony_ci                DBG(10, "error: saving parameter not supported\n");
381141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
382141cc406Sopenharmony_ci              case 0x47:
383141cc406Sopenharmony_ci                DBG(10, "SCSI parity error\n");
384141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
385141cc406Sopenharmony_ci              case 0x48:
386141cc406Sopenharmony_ci                DBG(10, "initiator detected error message received\n");
387141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
388141cc406Sopenharmony_ci              case 0x60:
389141cc406Sopenharmony_ci                DBG(1, "error: lamp failure\n");
390141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
391141cc406Sopenharmony_ci              case 0x62:
392141cc406Sopenharmony_ci                DBG(1, "scan head positioning error\n");
393141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
394141cc406Sopenharmony_ci            }
395141cc406Sopenharmony_ci
396141cc406Sopenharmony_ci        }
397141cc406Sopenharmony_ci      else if (sdat->model == JX250 || sdat->model == JX330 ||
398141cc406Sopenharmony_ci	       sdat->model == JX350 || sdat->model == JX320)
399141cc406Sopenharmony_ci        {
400141cc406Sopenharmony_ci          switch (sense_key)
401141cc406Sopenharmony_ci            {
402141cc406Sopenharmony_ci              case 0x02: /* not ready */
403141cc406Sopenharmony_ci                switch (add_sense_code)
404141cc406Sopenharmony_ci                  {
405141cc406Sopenharmony_ci                    case 0x80:
406141cc406Sopenharmony_ci                      switch (add_sense_qual)
407141cc406Sopenharmony_ci                        {
408141cc406Sopenharmony_ci                          case 0:
409141cc406Sopenharmony_ci                            DBG(1, "Scanner not ready: ADF cover open\n");
410141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR)
411141cc406Sopenharmony_ci                              return SANE_STATUS_COVER_OPEN;
412141cc406Sopenharmony_ci                            else
413141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
414141cc406Sopenharmony_ci                          case 1:
415141cc406Sopenharmony_ci                            DBG(1, "Scanner not ready: ADF maintenance "
416141cc406Sopenharmony_ci                                   "cover open\n");
417141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR)
418141cc406Sopenharmony_ci                              return SANE_STATUS_COVER_OPEN;
419141cc406Sopenharmony_ci                            else
420141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
421141cc406Sopenharmony_ci                          default:
422141cc406Sopenharmony_ci                            DBG(5, "Scanner not ready: undocumented reason\n");
423141cc406Sopenharmony_ci                            return SANE_STATUS_IO_ERROR;
424141cc406Sopenharmony_ci                        }
425141cc406Sopenharmony_ci                    case 0x81:
426141cc406Sopenharmony_ci                      /* NOT TESTED -- I don't have a FSU */
427141cc406Sopenharmony_ci                      switch (add_sense_qual)
428141cc406Sopenharmony_ci                        {
429141cc406Sopenharmony_ci                          case 0:
430141cc406Sopenharmony_ci                            DBG(1, "Scanner not ready: FSU cover open\n");
431141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR)
432141cc406Sopenharmony_ci                              return SANE_STATUS_COVER_OPEN;
433141cc406Sopenharmony_ci                            else
434141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
435141cc406Sopenharmony_ci                          case 1:
436141cc406Sopenharmony_ci                            DBG(1, "Scanner not ready: FSU light dispersion "
437141cc406Sopenharmony_ci                                   "error\n");
438141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR)
439141cc406Sopenharmony_ci                              {
440141cc406Sopenharmony_ci                                return SANE_STATUS_IO_ERROR;
441141cc406Sopenharmony_ci                              }
442141cc406Sopenharmony_ci                            else
443141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
444141cc406Sopenharmony_ci                          default:
445141cc406Sopenharmony_ci                            DBG(5, "Scanner not ready: undocumented reason\n");
446141cc406Sopenharmony_ci                            return SANE_STATUS_IO_ERROR;
447141cc406Sopenharmony_ci                        }
448141cc406Sopenharmony_ci                    default:
449141cc406Sopenharmony_ci                      DBG(5, "Scanner not ready: undocumented reason\n");
450141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
451141cc406Sopenharmony_ci                  }
452141cc406Sopenharmony_ci              case 0x03: /* medium error */
453141cc406Sopenharmony_ci                switch (add_sense_code)
454141cc406Sopenharmony_ci                  {
455141cc406Sopenharmony_ci                    case 0x3a:
456141cc406Sopenharmony_ci                      DBG(1, "ADF is empty\n");
457141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR)
458141cc406Sopenharmony_ci                              return SANE_STATUS_NO_DOCS;
459141cc406Sopenharmony_ci                            else
460141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
461141cc406Sopenharmony_ci                    case 0x53:
462141cc406Sopenharmony_ci                      DBG(1, "ADF paper jam\n"
463141cc406Sopenharmony_ci                             "Open and close the maintenance cover to clear "
464141cc406Sopenharmony_ci                             "this error\n");
465141cc406Sopenharmony_ci                            if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR)
466141cc406Sopenharmony_ci                              return SANE_STATUS_JAMMED;
467141cc406Sopenharmony_ci                            else
468141cc406Sopenharmony_ci                              return SANE_STATUS_GOOD;
469141cc406Sopenharmony_ci                    default:
470141cc406Sopenharmony_ci                      DBG(5, "medium error: undocumented reason\n");
471141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
472141cc406Sopenharmony_ci                  }
473141cc406Sopenharmony_ci              case 0x04: /* hardware error */
474141cc406Sopenharmony_ci                switch (add_sense_code)
475141cc406Sopenharmony_ci                  {
476141cc406Sopenharmony_ci                    case 0x08:
477141cc406Sopenharmony_ci                      DBG(1, "hardware error: scanner communication failed\n");
478141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
479141cc406Sopenharmony_ci                    case 0x60:
480141cc406Sopenharmony_ci                      DBG(1, "hardware error: lamp failure\n");
481141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
482141cc406Sopenharmony_ci                    case 0x62:
483141cc406Sopenharmony_ci                      DBG(1, "hardware error: scan head positioning failed\n");
484141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
485141cc406Sopenharmony_ci                    default:
486141cc406Sopenharmony_ci                      DBG(1, "general hardware error\n");
487141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
488141cc406Sopenharmony_ci                  }
489141cc406Sopenharmony_ci              case 0x05: /* illegal request */
490141cc406Sopenharmony_ci                DBG(10, "error: illegal request\n");
491141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
492141cc406Sopenharmony_ci              case 0x06: /* unit attention */
493141cc406Sopenharmony_ci                switch (add_sense_code)
494141cc406Sopenharmony_ci                  {
495141cc406Sopenharmony_ci                    case 0x29:
496141cc406Sopenharmony_ci                      DBG(5, "unit attention: reset occurred\n");
497141cc406Sopenharmony_ci                      return SANE_STATUS_GOOD;
498141cc406Sopenharmony_ci                    case 0x2a:
499141cc406Sopenharmony_ci                      DBG(5, "unit attention: parameter changed by "
500141cc406Sopenharmony_ci                             "another initiator\n");
501141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
502141cc406Sopenharmony_ci                    default:
503141cc406Sopenharmony_ci                      DBG(5, "unit attention: exact reason not documented\n");
504141cc406Sopenharmony_ci                      return SANE_STATUS_IO_ERROR;
505141cc406Sopenharmony_ci                  }
506141cc406Sopenharmony_ci              case 0x09: /* data remains */
507141cc406Sopenharmony_ci                DBG(5, "error: data remains\n");
508141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
509141cc406Sopenharmony_ci              default:
510141cc406Sopenharmony_ci                DBG(5, "error: sense code not documented\n");
511141cc406Sopenharmony_ci                return SANE_STATUS_IO_ERROR;
512141cc406Sopenharmony_ci            }
513141cc406Sopenharmony_ci        }
514141cc406Sopenharmony_ci    }
515141cc406Sopenharmony_ci  return SANE_STATUS_IO_ERROR;
516141cc406Sopenharmony_ci}
517141cc406Sopenharmony_ci
518141cc406Sopenharmony_cistatic SANE_Status
519141cc406Sopenharmony_citest_unit_ready (int fd)
520141cc406Sopenharmony_ci{
521141cc406Sopenharmony_ci  static u_char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
522141cc406Sopenharmony_ci  SANE_Status status;
523141cc406Sopenharmony_ci  DBG (11, "<< test_unit_ready ");
524141cc406Sopenharmony_ci
525141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
526141cc406Sopenharmony_ci
527141cc406Sopenharmony_ci  DBG (11, ">>\n");
528141cc406Sopenharmony_ci  return (status);
529141cc406Sopenharmony_ci}
530141cc406Sopenharmony_ci
531141cc406Sopenharmony_ci#if 0
532141cc406Sopenharmony_cistatic SANE_Status
533141cc406Sopenharmony_cirequest_sense (int fd, void *sense_buf, size_t *sense_size)
534141cc406Sopenharmony_ci{
535141cc406Sopenharmony_ci  static u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, SENSE_LEN, 0};
536141cc406Sopenharmony_ci  SANE_Status status;
537141cc406Sopenharmony_ci  DBG (11, "<< request_sense ");
538141cc406Sopenharmony_ci
539141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_buf, sense_size);
540141cc406Sopenharmony_ci
541141cc406Sopenharmony_ci  DBG (11, ">>\n");
542141cc406Sopenharmony_ci  return (status);
543141cc406Sopenharmony_ci}
544141cc406Sopenharmony_ci#endif
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_cistatic SANE_Status
547141cc406Sopenharmony_ciinquiry (int fd, void *inq_buf, size_t *inq_size)
548141cc406Sopenharmony_ci{
549141cc406Sopenharmony_ci  static u_char cmd[] = {INQUIRY, 0, 0, 0, INQUIRY_LEN, 0};
550141cc406Sopenharmony_ci  SANE_Status status;
551141cc406Sopenharmony_ci  DBG (11, "<< inquiry ");
552141cc406Sopenharmony_ci
553141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), inq_buf, inq_size);
554141cc406Sopenharmony_ci
555141cc406Sopenharmony_ci  DBG (11, ">>\n");
556141cc406Sopenharmony_ci  return (status);
557141cc406Sopenharmony_ci}
558141cc406Sopenharmony_ci
559141cc406Sopenharmony_cistatic SANE_Status
560141cc406Sopenharmony_cimode_select_mud (int fd, int mud)
561141cc406Sopenharmony_ci{
562141cc406Sopenharmony_ci  static u_char cmd[6 + MODEPARAM_LEN] =
563141cc406Sopenharmony_ci                        {MODE_SELECT6, 0x10, 0, 0, MODEPARAM_LEN, 0};
564141cc406Sopenharmony_ci  mode_select_param *mp;
565141cc406Sopenharmony_ci  SANE_Status status;
566141cc406Sopenharmony_ci  DBG (11, "<< mode_select_mud ");
567141cc406Sopenharmony_ci
568141cc406Sopenharmony_ci  mp = (mode_select_param *)(cmd + 6);
569141cc406Sopenharmony_ci  memset (mp, 0, MODEPARAM_LEN);
570141cc406Sopenharmony_ci  mp->page_code = 3;
571141cc406Sopenharmony_ci  mp->page_length = 6;
572141cc406Sopenharmony_ci  mp->mud[0] = mud >> 8;
573141cc406Sopenharmony_ci  mp->mud[1] = mud & 0xFF;
574141cc406Sopenharmony_ci
575141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
576141cc406Sopenharmony_ci
577141cc406Sopenharmony_ci  DBG (11, ">>\n");
578141cc406Sopenharmony_ci  return (status);
579141cc406Sopenharmony_ci}
580141cc406Sopenharmony_ci
581141cc406Sopenharmony_cistatic SANE_Status
582141cc406Sopenharmony_cimode_select_adf_fsu (int fd, int mode)
583141cc406Sopenharmony_ci{
584141cc406Sopenharmony_ci  static u_char cmd[6 + MODE_SUBDEV_LEN] =
585141cc406Sopenharmony_ci                        {MODE_SELECT6, 0x10, 0, 0, MODE_SUBDEV_LEN, 0};
586141cc406Sopenharmony_ci  mode_select_subdevice *mp;
587141cc406Sopenharmony_ci  SANE_Status status;
588141cc406Sopenharmony_ci  DBG (11, "<< mode_select_adf_fsu ");
589141cc406Sopenharmony_ci
590141cc406Sopenharmony_ci  mp = (mode_select_subdevice *)(cmd + 6);
591141cc406Sopenharmony_ci  memset (mp, 0, MODE_SUBDEV_LEN);
592141cc406Sopenharmony_ci  mp->page_code = 0x20;
593141cc406Sopenharmony_ci  mp->page_length = 26;
594141cc406Sopenharmony_ci  switch (mode)
595141cc406Sopenharmony_ci    {
596141cc406Sopenharmony_ci      case SCAN_SIMPLE:
597141cc406Sopenharmony_ci        mp->a_mode = 0x40;
598141cc406Sopenharmony_ci        mp->f_mode = 0x40;
599141cc406Sopenharmony_ci        break;
600141cc406Sopenharmony_ci      case SCAN_WITH_FSU:
601141cc406Sopenharmony_ci        mp->a_mode = 0;
602141cc406Sopenharmony_ci        mp->f_mode = 0x40;
603141cc406Sopenharmony_ci        break;
604141cc406Sopenharmony_ci      case SCAN_WITH_ADF:
605141cc406Sopenharmony_ci        mp->a_mode = 0x40;
606141cc406Sopenharmony_ci        mp->f_mode = 0;
607141cc406Sopenharmony_ci        break;
608141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
609141cc406Sopenharmony_ci      case: SCAN_ADF_FSU_AUTO:
610141cc406Sopenharmony_ci        mp->a_mode = 0;
611141cc406Sopenharmony_ci        mp->f_mode = 0;
612141cc406Sopenharmony_ci        break;
613141cc406Sopenharmony_ci#endif
614141cc406Sopenharmony_ci    }
615141cc406Sopenharmony_ci
616141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
617141cc406Sopenharmony_ci
618141cc406Sopenharmony_ci  DBG (11, ">>\n");
619141cc406Sopenharmony_ci  return (status);
620141cc406Sopenharmony_ci}
621141cc406Sopenharmony_ci
622141cc406Sopenharmony_cistatic SANE_Status wait_ready(int fd);
623141cc406Sopenharmony_ci
624141cc406Sopenharmony_cistatic SANE_Status
625141cc406Sopenharmony_ciobject_position(int fd, int load)
626141cc406Sopenharmony_ci{
627141cc406Sopenharmony_ci  static u_char cmd[] = {OBJECT_POSITION, 0, 0, 0, 0, 0, 0, 0, 0, 0};
628141cc406Sopenharmony_ci  SANE_Status status;
629141cc406Sopenharmony_ci  DBG (11, "<< object_position ");
630141cc406Sopenharmony_ci
631141cc406Sopenharmony_ci  cmd[1] = load;
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_ci  wait_ready(fd);
634141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
635141cc406Sopenharmony_ci
636141cc406Sopenharmony_ci  DBG (11, ">>\n");
637141cc406Sopenharmony_ci  return (status);
638141cc406Sopenharmony_ci}
639141cc406Sopenharmony_ci
640141cc406Sopenharmony_ci#if 0
641141cc406Sopenharmony_cistatic SANE_Status
642141cc406Sopenharmony_cireserve_unit (int fd)
643141cc406Sopenharmony_ci{
644141cc406Sopenharmony_ci  static u_char cmd[] = {RESERVE_UNIT, 0, 0, 0, 0, 0};
645141cc406Sopenharmony_ci  SANE_Status status;
646141cc406Sopenharmony_ci  DBG (11, "<< reserve_unit ");
647141cc406Sopenharmony_ci
648141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
649141cc406Sopenharmony_ci
650141cc406Sopenharmony_ci  DBG (11, ">>\n");
651141cc406Sopenharmony_ci  return (status);
652141cc406Sopenharmony_ci}
653141cc406Sopenharmony_ci#endif
654141cc406Sopenharmony_ci
655141cc406Sopenharmony_ci#if 0
656141cc406Sopenharmony_cistatic SANE_Status
657141cc406Sopenharmony_cirelease_unit (int fd)
658141cc406Sopenharmony_ci{
659141cc406Sopenharmony_ci  static u_char cmd[] = {RELEASE_UNIT, 0, 0, 0, 0, 0};
660141cc406Sopenharmony_ci  SANE_Status status;
661141cc406Sopenharmony_ci  DBG (11, "<< release_unit ");
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
664141cc406Sopenharmony_ci
665141cc406Sopenharmony_ci  DBG (11, ">>\n");
666141cc406Sopenharmony_ci  return (status);
667141cc406Sopenharmony_ci}
668141cc406Sopenharmony_ci#endif
669141cc406Sopenharmony_ci
670141cc406Sopenharmony_cistatic SANE_Status
671141cc406Sopenharmony_cimode_sense (int fd, void *modeparam_buf, size_t * modeparam_size,
672141cc406Sopenharmony_ci            int page)
673141cc406Sopenharmony_ci{
674141cc406Sopenharmony_ci  static u_char cmd[6];
675141cc406Sopenharmony_ci  SANE_Status status;
676141cc406Sopenharmony_ci  DBG (11, "<< mode_sense ");
677141cc406Sopenharmony_ci
678141cc406Sopenharmony_ci  memset (cmd, 0, sizeof (cmd));
679141cc406Sopenharmony_ci  cmd[0] = 0x1a;
680141cc406Sopenharmony_ci  cmd[2] = page;
681141cc406Sopenharmony_ci  cmd[4] = *modeparam_size;
682141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), modeparam_buf,
683141cc406Sopenharmony_ci			   modeparam_size);
684141cc406Sopenharmony_ci
685141cc406Sopenharmony_ci  DBG (11, ">>\n");
686141cc406Sopenharmony_ci  return (status);
687141cc406Sopenharmony_ci}
688141cc406Sopenharmony_ci
689141cc406Sopenharmony_cistatic SANE_Status
690141cc406Sopenharmony_ciscan (int fd)
691141cc406Sopenharmony_ci{
692141cc406Sopenharmony_ci  static u_char cmd[] = {SCAN, 0, 0, 0, 0, 0};
693141cc406Sopenharmony_ci  SANE_Status status;
694141cc406Sopenharmony_ci  DBG (11, "<< scan ");
695141cc406Sopenharmony_ci
696141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
697141cc406Sopenharmony_ci
698141cc406Sopenharmony_ci  DBG (11, ">>\n");
699141cc406Sopenharmony_ci  return (status);
700141cc406Sopenharmony_ci}
701141cc406Sopenharmony_ci
702141cc406Sopenharmony_ci#if 0
703141cc406Sopenharmony_cistatic SANE_Status
704141cc406Sopenharmony_cisend_diagnostics (int fd)
705141cc406Sopenharmony_ci{
706141cc406Sopenharmony_ci  static u_char cmd[] = {SEND_DIAGNOSTIC, 0x04, 0, 0, 0, 0};
707141cc406Sopenharmony_ci  SANE_Status status;
708141cc406Sopenharmony_ci  DBG (11, "<< send_diagnostics ");
709141cc406Sopenharmony_ci
710141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
711141cc406Sopenharmony_ci
712141cc406Sopenharmony_ci  DBG (11, ">>\n");
713141cc406Sopenharmony_ci  return (status);
714141cc406Sopenharmony_ci}
715141cc406Sopenharmony_ci#endif
716141cc406Sopenharmony_ci
717141cc406Sopenharmony_cistatic SANE_Status
718141cc406Sopenharmony_cisend (int fd, SHARP_Send * ss)
719141cc406Sopenharmony_ci{
720141cc406Sopenharmony_ci  static u_char cmd[] = {SEND, 0, 0, 0, 0, 0, 0, 0, 0, 0};
721141cc406Sopenharmony_ci  SANE_Status status;
722141cc406Sopenharmony_ci  DBG (11, "<< send ");
723141cc406Sopenharmony_ci
724141cc406Sopenharmony_ci  cmd[2] = ss->dtc;
725141cc406Sopenharmony_ci  cmd[4] = ss->dtq >> 8;
726141cc406Sopenharmony_ci  cmd[5] = ss->dtq;
727141cc406Sopenharmony_ci  cmd[6] = ss->length >> 16;
728141cc406Sopenharmony_ci  cmd[7] = ss->length >>  8;
729141cc406Sopenharmony_ci  cmd[8] = ss->length >>  0;
730141cc406Sopenharmony_ci
731141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
732141cc406Sopenharmony_ci
733141cc406Sopenharmony_ci  DBG (11, ">>\n");
734141cc406Sopenharmony_ci  return (status);
735141cc406Sopenharmony_ci
736141cc406Sopenharmony_ci}
737141cc406Sopenharmony_ci
738141cc406Sopenharmony_cistatic SANE_Status
739141cc406Sopenharmony_ciset_window (int fd, window_param *wp, int len)
740141cc406Sopenharmony_ci{
741141cc406Sopenharmony_ci  static u_char cmd[10 + WINDOW_LEN] =
742141cc406Sopenharmony_ci                        {SET_WINDOW, 0, 0, 0, 0, 0, 0, 0, 0, 0};
743141cc406Sopenharmony_ci  window_param *winp;
744141cc406Sopenharmony_ci  SANE_Status status;
745141cc406Sopenharmony_ci  DBG (11, "<< set_window ");
746141cc406Sopenharmony_ci
747141cc406Sopenharmony_ci  cmd[8] = len;
748141cc406Sopenharmony_ci  winp = (window_param *)(cmd + 10);
749141cc406Sopenharmony_ci  memset (winp, 0, WINDOW_LEN);
750141cc406Sopenharmony_ci  memcpy (winp, wp, len);
751141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
752141cc406Sopenharmony_ci
753141cc406Sopenharmony_ci  DBG (11, ">>\n");
754141cc406Sopenharmony_ci  return (status);
755141cc406Sopenharmony_ci
756141cc406Sopenharmony_ci}
757141cc406Sopenharmony_ci
758141cc406Sopenharmony_cistatic SANE_Status
759141cc406Sopenharmony_ciget_window (int fd, void *buf, size_t * buf_size)
760141cc406Sopenharmony_ci{
761141cc406Sopenharmony_ci
762141cc406Sopenharmony_ci  static u_char cmd[10] = {GET_WINDOW, 0, 0, 0, 0, 0, 0, 0, WINDOW_LEN, 0};
763141cc406Sopenharmony_ci  SANE_Status status;
764141cc406Sopenharmony_ci  DBG (11, "<< get_window ");
765141cc406Sopenharmony_ci
766141cc406Sopenharmony_ci  cmd[8] = *buf_size;
767141cc406Sopenharmony_ci  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size);
768141cc406Sopenharmony_ci
769141cc406Sopenharmony_ci  DBG (11, ">>\n");
770141cc406Sopenharmony_ci  return (status);
771141cc406Sopenharmony_ci}
772141cc406Sopenharmony_ci
773141cc406Sopenharmony_ci#ifdef USE_FORK
774141cc406Sopenharmony_ci
775141cc406Sopenharmony_ci/* the following four functions serve simply the purpose
776141cc406Sopenharmony_ci   to avoid "over-optimised" code when reader_process and
777141cc406Sopenharmony_ci   read_data wait for the buffer to become ready. The simple
778141cc406Sopenharmony_ci   while-loops in these functions which check the buffer
779141cc406Sopenharmony_ci   status may be optimised so that the machine code only
780141cc406Sopenharmony_ci   operates with registers instead of using the variable
781141cc406Sopenharmony_ci   values stored in memory. (This is only a workaround -
782141cc406Sopenharmony_ci   it would be better to set a compiler pragma, which ensures
783141cc406Sopenharmony_ci   that the program looks into the RAM in these while loops --
784141cc406Sopenharmony_ci   but unfortunately I could not find appropriate information
785141cc406Sopenharmony_ci   about this at least for gcc, not to speak about other
786141cc406Sopenharmony_ci   compilers...
787141cc406Sopenharmony_ci   Abel)
788141cc406Sopenharmony_ci*/
789141cc406Sopenharmony_ci
790141cc406Sopenharmony_cistatic int
791141cc406Sopenharmony_cicancel_requested(SHARP_Scanner *s)
792141cc406Sopenharmony_ci{
793141cc406Sopenharmony_ci  return s->rdr_ctl->cancel;
794141cc406Sopenharmony_ci}
795141cc406Sopenharmony_ci
796141cc406Sopenharmony_cistatic SANE_Status
797141cc406Sopenharmony_cirdr_status(SHARP_Scanner *s)
798141cc406Sopenharmony_ci{
799141cc406Sopenharmony_ci  return s->rdr_ctl->status;
800141cc406Sopenharmony_ci}
801141cc406Sopenharmony_ci
802141cc406Sopenharmony_cistatic int
803141cc406Sopenharmony_cibuf_status(SHARP_shmem_ctl *s)
804141cc406Sopenharmony_ci{
805141cc406Sopenharmony_ci  return s->shm_status;
806141cc406Sopenharmony_ci}
807141cc406Sopenharmony_ci
808141cc406Sopenharmony_cistatic int
809141cc406Sopenharmony_cireader_running(SHARP_Scanner *s)
810141cc406Sopenharmony_ci{
811141cc406Sopenharmony_ci  return s->rdr_ctl->running;
812141cc406Sopenharmony_ci}
813141cc406Sopenharmony_ci
814141cc406Sopenharmony_cistatic int
815141cc406Sopenharmony_cireader_process(SHARP_Scanner *s)
816141cc406Sopenharmony_ci{
817141cc406Sopenharmony_ci  SANE_Status status;
818141cc406Sopenharmony_ci  sigset_t sigterm_set;
819141cc406Sopenharmony_ci  static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0};
820141cc406Sopenharmony_ci  int full_count = 0, counted;
821141cc406Sopenharmony_ci  size_t waitindex, cmdindex;
822141cc406Sopenharmony_ci  size_t bytes_to_queue;
823141cc406Sopenharmony_ci  size_t nread;
824141cc406Sopenharmony_ci  size_t max_bytes_per_read;
825141cc406Sopenharmony_ci  int max_queue;
826141cc406Sopenharmony_ci  int i, retries = MAX_RETRIES;
827141cc406Sopenharmony_ci  SHARP_shmem_ctl *bc;
828141cc406Sopenharmony_ci
829141cc406Sopenharmony_ci  s->rdr_ctl->running = 1;
830141cc406Sopenharmony_ci  DBG(11, "<< reader_process\n");
831141cc406Sopenharmony_ci
832141cc406Sopenharmony_ci  sigemptyset (&sigterm_set);
833141cc406Sopenharmony_ci
834141cc406Sopenharmony_ci  bytes_to_queue = s->bytes_to_read;
835141cc406Sopenharmony_ci
836141cc406Sopenharmony_ci  /* it seems that some carriage stops can be avoided with the
837141cc406Sopenharmony_ci     JX-250, if the data of an integral number of scan lines is
838141cc406Sopenharmony_ci     read with one SCSI command
839141cc406Sopenharmony_ci  */
840141cc406Sopenharmony_ci  max_bytes_per_read = s->dev->info.bufsize / s->params.bytes_per_line;
841141cc406Sopenharmony_ci  if (max_bytes_per_read)
842141cc406Sopenharmony_ci    max_bytes_per_read *= s->params.bytes_per_line;
843141cc406Sopenharmony_ci  else
844141cc406Sopenharmony_ci    /* this is a really tiny buffer..*/
845141cc406Sopenharmony_ci    max_bytes_per_read = s->dev->info.bufsize;
846141cc406Sopenharmony_ci
847141cc406Sopenharmony_ci  /*  wait_ready(s->fd); */
848141cc406Sopenharmony_ci
849141cc406Sopenharmony_ci  if (s->dev->info.queued_reads <= s->dev->info.buffers)
850141cc406Sopenharmony_ci    max_queue = s->dev->info.queued_reads;
851141cc406Sopenharmony_ci  else
852141cc406Sopenharmony_ci    max_queue = s->dev->info.buffers;
853141cc406Sopenharmony_ci  if (max_queue <= 0)
854141cc406Sopenharmony_ci    max_queue = 1;
855141cc406Sopenharmony_ci  for (i = 0; i < max_queue; i++)
856141cc406Sopenharmony_ci    {
857141cc406Sopenharmony_ci      bc = &s->rdr_ctl->buf_ctl[i];
858141cc406Sopenharmony_ci      if (bytes_to_queue)
859141cc406Sopenharmony_ci        {
860141cc406Sopenharmony_ci          nread = bytes_to_queue;
861141cc406Sopenharmony_ci          if (nread > max_bytes_per_read)
862141cc406Sopenharmony_ci            nread = max_bytes_per_read;
863141cc406Sopenharmony_ci          bc->used = nread;
864141cc406Sopenharmony_ci          cmd[6] = nread >> 16;
865141cc406Sopenharmony_ci          cmd[7] = nread >> 8;
866141cc406Sopenharmony_ci          cmd[8] = nread;
867141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
868141cc406Sopenharmony_ci          DBG(2, "reader: req_enter...\n");
869141cc406Sopenharmony_ci#endif
870141cc406Sopenharmony_ci          status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd),
871141cc406Sopenharmony_ci                     bc->buffer,
872141cc406Sopenharmony_ci                    &bc->used,
873141cc406Sopenharmony_ci                    &bc->qid);
874141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
875141cc406Sopenharmony_ci          DBG(2, "reader: req_enter ok\n");
876141cc406Sopenharmony_ci#endif
877141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
878141cc406Sopenharmony_ci            {
879141cc406Sopenharmony_ci              DBG(1, "reader_process: read command failed: %s",
880141cc406Sopenharmony_ci                  sane_strstatus(status));
881141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
882141cc406Sopenharmony_ci              sanei_scsi_req_flush_all_extended(s->fd);
883141cc406Sopenharmony_ci#else
884141cc406Sopenharmony_ci               sanei_scsi_req_flush_all();
885141cc406Sopenharmony_ci#endif
886141cc406Sopenharmony_ci              s->rdr_ctl->status = status;
887141cc406Sopenharmony_ci              s->rdr_ctl->running = 0;
888141cc406Sopenharmony_ci              return 2;
889141cc406Sopenharmony_ci            }
890141cc406Sopenharmony_ci          bc->shm_status = SHM_BUSY;
891141cc406Sopenharmony_ci          bc->nreq = bc->used;
892141cc406Sopenharmony_ci          bytes_to_queue -= bc->nreq;
893141cc406Sopenharmony_ci        }
894141cc406Sopenharmony_ci      else
895141cc406Sopenharmony_ci        {
896141cc406Sopenharmony_ci          bc->used = 0;
897141cc406Sopenharmony_ci          bc->shm_status = SHM_EMPTY;
898141cc406Sopenharmony_ci        }
899141cc406Sopenharmony_ci    }
900141cc406Sopenharmony_ci  waitindex = 0;
901141cc406Sopenharmony_ci  cmdindex = i % s->dev->info.buffers;
902141cc406Sopenharmony_ci
903141cc406Sopenharmony_ci  while(s->bytes_to_read > 0)
904141cc406Sopenharmony_ci    {
905141cc406Sopenharmony_ci      if (cancel_requested(s))
906141cc406Sopenharmony_ci        {
907141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
908141cc406Sopenharmony_ci          DBG(2, "reader: flushing requests...\n");
909141cc406Sopenharmony_ci#endif
910141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
911141cc406Sopenharmony_ci          sanei_scsi_req_flush_all_extended(s->fd);
912141cc406Sopenharmony_ci#else
913141cc406Sopenharmony_ci          sanei_scsi_req_flush_all();
914141cc406Sopenharmony_ci#endif
915141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
916141cc406Sopenharmony_ci          DBG(2, "reader: flushing requests ok\n");
917141cc406Sopenharmony_ci#endif
918141cc406Sopenharmony_ci          s->rdr_ctl->cancel = 0;
919141cc406Sopenharmony_ci          s->rdr_ctl->status = SANE_STATUS_CANCELLED;
920141cc406Sopenharmony_ci          s->rdr_ctl->running = 0;
921141cc406Sopenharmony_ci          DBG(11, " reader_process (cancelled) >>\n");
922141cc406Sopenharmony_ci          return 1;
923141cc406Sopenharmony_ci        }
924141cc406Sopenharmony_ci
925141cc406Sopenharmony_ci      bc = &s->rdr_ctl->buf_ctl[waitindex];
926141cc406Sopenharmony_ci      if (bc->shm_status == SHM_BUSY)
927141cc406Sopenharmony_ci        {
928141cc406Sopenharmony_ci#ifdef DEBUG
929141cc406Sopenharmony_ci          {
930141cc406Sopenharmony_ci            struct timeval t;
931141cc406Sopenharmony_ci            gettimeofday(&t, 0);
932141cc406Sopenharmony_ci            DBG(2, "rd: waiting for data %li.%06li\n", t.tv_sec, t.tv_usec);
933141cc406Sopenharmony_ci          }
934141cc406Sopenharmony_ci#endif
935141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
936141cc406Sopenharmony_ci          DBG(2, "reader: req_wait...\n");
937141cc406Sopenharmony_ci#endif
938141cc406Sopenharmony_ci          status = sanei_scsi_req_wait(bc->qid);
939141cc406Sopenharmony_ci#ifdef QUEUEDEBUG
940141cc406Sopenharmony_ci          DBG(2, "reader: req_wait ok\n");
941141cc406Sopenharmony_ci#endif
942141cc406Sopenharmony_ci#ifdef DEBUG
943141cc406Sopenharmony_ci          {
944141cc406Sopenharmony_ci            struct timeval t;
945141cc406Sopenharmony_ci            gettimeofday(&t, 0);
946141cc406Sopenharmony_ci            DBG(2, "rd: data received    %li.%06li\n", t.tv_sec, t.tv_usec);
947141cc406Sopenharmony_ci          }
948141cc406Sopenharmony_ci#endif
949141cc406Sopenharmony_ci          if (status == SANE_STATUS_DEVICE_BUSY && retries)
950141cc406Sopenharmony_ci            {
951141cc406Sopenharmony_ci              bc->used = 0;
952141cc406Sopenharmony_ci              retries--;
953141cc406Sopenharmony_ci              DBG(11, "reader: READ command returned BUSY\n");
954141cc406Sopenharmony_ci              status = SANE_STATUS_GOOD;
955141cc406Sopenharmony_ci              usleep(10000);
956141cc406Sopenharmony_ci            }
957141cc406Sopenharmony_ci          else if (status != SANE_STATUS_GOOD)
958141cc406Sopenharmony_ci            {
959141cc406Sopenharmony_ci              DBG(1, "reader_process: read command failed: %s\n",
960141cc406Sopenharmony_ci                  sane_strstatus(status));
961141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
962141cc406Sopenharmony_ci              sanei_scsi_req_flush_all_extended(s->fd);
963141cc406Sopenharmony_ci#else
964141cc406Sopenharmony_ci              sanei_scsi_req_flush_all();
965141cc406Sopenharmony_ci#endif
966141cc406Sopenharmony_ci              s->rdr_ctl->status = status;
967141cc406Sopenharmony_ci              s->rdr_ctl->running = 0;
968141cc406Sopenharmony_ci              return 2;
969141cc406Sopenharmony_ci            }
970141cc406Sopenharmony_ci          else
971141cc406Sopenharmony_ci            {
972141cc406Sopenharmony_ci              retries = MAX_RETRIES;
973141cc406Sopenharmony_ci            }
974141cc406Sopenharmony_ci#if 1
975141cc406Sopenharmony_ci          s->bytes_to_read -= bc->used;
976141cc406Sopenharmony_ci          bytes_to_queue += bc->nreq - bc->used;
977141cc406Sopenharmony_ci#else
978141cc406Sopenharmony_ci          /* xxxxxxxxxxxxxxxxxxx TEST xxxxxxxxxxxxxxx */
979141cc406Sopenharmony_ci          s->bytes_to_read -= bc->nreq;
980141cc406Sopenharmony_ci          /* memset(bc->buffer + bc->used, 0, bc->nreq - bc->used); */
981141cc406Sopenharmony_ci          bc->used = bc->nreq;
982141cc406Sopenharmony_ci          /* bytes_to_queue += bc->nreq - bc->used; */
983141cc406Sopenharmony_ci          DBG(1, "btr: %i btq: %i nreq: %i nrcv: %i\n",
984141cc406Sopenharmony_ci            s->bytes_to_read, bytes_to_queue, bc->nreq, bc->used);
985141cc406Sopenharmony_ci#endif
986141cc406Sopenharmony_ci          bc->start = 0;
987141cc406Sopenharmony_ci          bc->shm_status = SHM_FULL;
988141cc406Sopenharmony_ci
989141cc406Sopenharmony_ci          waitindex++;
990141cc406Sopenharmony_ci          if (waitindex == s->dev->info.buffers)
991141cc406Sopenharmony_ci            waitindex = 0;
992141cc406Sopenharmony_ci
993141cc406Sopenharmony_ci        }
994141cc406Sopenharmony_ci
995141cc406Sopenharmony_ci      if (bytes_to_queue)
996141cc406Sopenharmony_ci        {
997141cc406Sopenharmony_ci          /* wait until the next buffer is completely read via read_data */
998141cc406Sopenharmony_ci          bc = &s->rdr_ctl->buf_ctl[cmdindex];
999141cc406Sopenharmony_ci          counted = 0;
1000141cc406Sopenharmony_ci          while (buf_status(bc) != SHM_EMPTY)
1001141cc406Sopenharmony_ci            {
1002141cc406Sopenharmony_ci              if (!counted)
1003141cc406Sopenharmony_ci                {
1004141cc406Sopenharmony_ci                  counted = 1;
1005141cc406Sopenharmony_ci                  full_count++;
1006141cc406Sopenharmony_ci                }
1007141cc406Sopenharmony_ci              if (cancel_requested(s))
1008141cc406Sopenharmony_ci                {
1009141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
1010141cc406Sopenharmony_ci                  sanei_scsi_req_flush_all_extended(s->fd);
1011141cc406Sopenharmony_ci#else
1012141cc406Sopenharmony_ci                  sanei_scsi_req_flush_all();
1013141cc406Sopenharmony_ci#endif
1014141cc406Sopenharmony_ci                  s->rdr_ctl->cancel = 0;
1015141cc406Sopenharmony_ci                  s->rdr_ctl->status = SANE_STATUS_CANCELLED;
1016141cc406Sopenharmony_ci                  s->rdr_ctl->running = 0;
1017141cc406Sopenharmony_ci                  DBG(11, " reader_process (cancelled) >>\n");
1018141cc406Sopenharmony_ci                  return 1;
1019141cc406Sopenharmony_ci                }
1020141cc406Sopenharmony_ci            }
1021141cc406Sopenharmony_ci
1022141cc406Sopenharmony_ci          nread = bytes_to_queue;
1023141cc406Sopenharmony_ci          if (nread > max_bytes_per_read)
1024141cc406Sopenharmony_ci            nread = max_bytes_per_read;
1025141cc406Sopenharmony_ci          bc->used = nread;
1026141cc406Sopenharmony_ci          cmd[6] = nread >> 16;
1027141cc406Sopenharmony_ci          cmd[7] = nread >> 8;
1028141cc406Sopenharmony_ci          cmd[8] = nread;
1029141cc406Sopenharmony_ci          status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd),
1030141cc406Sopenharmony_ci                    bc->buffer, &bc->used, &bc->qid);
1031141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
1032141cc406Sopenharmony_ci            {
1033141cc406Sopenharmony_ci              DBG(1, "reader_process: read command failed: %s",
1034141cc406Sopenharmony_ci                  sane_strstatus(status));
1035141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
1036141cc406Sopenharmony_ci              sanei_scsi_req_flush_all_extended(s->fd);
1037141cc406Sopenharmony_ci#else
1038141cc406Sopenharmony_ci              sanei_scsi_req_flush_all();
1039141cc406Sopenharmony_ci#endif
1040141cc406Sopenharmony_ci              s->rdr_ctl->status = status;
1041141cc406Sopenharmony_ci              s->rdr_ctl->running = 0;
1042141cc406Sopenharmony_ci              return 2;
1043141cc406Sopenharmony_ci            }
1044141cc406Sopenharmony_ci          bc->shm_status = SHM_BUSY;
1045141cc406Sopenharmony_ci          bc->nreq = nread;
1046141cc406Sopenharmony_ci          bytes_to_queue -= nread;
1047141cc406Sopenharmony_ci
1048141cc406Sopenharmony_ci          cmdindex++;
1049141cc406Sopenharmony_ci          if (cmdindex == s->dev->info.buffers)
1050141cc406Sopenharmony_ci            cmdindex = 0;
1051141cc406Sopenharmony_ci        }
1052141cc406Sopenharmony_ci
1053141cc406Sopenharmony_ci      if (cancel_requested(s))
1054141cc406Sopenharmony_ci        {
1055141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
1056141cc406Sopenharmony_ci          sanei_scsi_req_flush_all_extended(s->fd);
1057141cc406Sopenharmony_ci#else
1058141cc406Sopenharmony_ci          sanei_scsi_req_flush_all();
1059141cc406Sopenharmony_ci#endif
1060141cc406Sopenharmony_ci          s->rdr_ctl->cancel = 0;
1061141cc406Sopenharmony_ci          s->rdr_ctl->status = SANE_STATUS_CANCELLED;
1062141cc406Sopenharmony_ci          s->rdr_ctl->running = 0;
1063141cc406Sopenharmony_ci          DBG(11, " reader_process (cancelled) >>\n");
1064141cc406Sopenharmony_ci          return 1;
1065141cc406Sopenharmony_ci        }
1066141cc406Sopenharmony_ci    }
1067141cc406Sopenharmony_ci
1068141cc406Sopenharmony_ci  DBG(1, "buffer full conditions: %i\n", full_count);
1069141cc406Sopenharmony_ci  DBG(11, " reader_process>>\n");
1070141cc406Sopenharmony_ci
1071141cc406Sopenharmony_ci  s->rdr_ctl->running = 0;
1072141cc406Sopenharmony_ci  return 0;
1073141cc406Sopenharmony_ci}
1074141cc406Sopenharmony_ci
1075141cc406Sopenharmony_cistatic SANE_Status
1076141cc406Sopenharmony_ciread_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size)
1077141cc406Sopenharmony_ci{
1078141cc406Sopenharmony_ci  size_t copysize, copied = 0;
1079141cc406Sopenharmony_ci  SHARP_shmem_ctl *bc;
1080141cc406Sopenharmony_ci
1081141cc406Sopenharmony_ci  DBG(11, "<< read_data ");
1082141cc406Sopenharmony_ci
1083141cc406Sopenharmony_ci  bc = &s->rdr_ctl->buf_ctl[s->read_buff];
1084141cc406Sopenharmony_ci
1085141cc406Sopenharmony_ci  while (copied < *buf_size)
1086141cc406Sopenharmony_ci    {
1087141cc406Sopenharmony_ci      /* wait until the reader process delivers data or a scanner error occurs: */
1088141cc406Sopenharmony_ci      while (   buf_status(bc) != SHM_FULL
1089141cc406Sopenharmony_ci             && rdr_status(s) == SANE_STATUS_GOOD)
1090141cc406Sopenharmony_ci        {
1091141cc406Sopenharmony_ci          usleep(10); /* could perhaps be longer. make this user configurable?? */
1092141cc406Sopenharmony_ci        }
1093141cc406Sopenharmony_ci
1094141cc406Sopenharmony_ci      if (rdr_status(s) != SANE_STATUS_GOOD)
1095141cc406Sopenharmony_ci        {
1096141cc406Sopenharmony_ci          return rdr_status(s);
1097141cc406Sopenharmony_ci          DBG(11, ">>\n");
1098141cc406Sopenharmony_ci        }
1099141cc406Sopenharmony_ci
1100141cc406Sopenharmony_ci      copysize = bc->used - bc->start;
1101141cc406Sopenharmony_ci
1102141cc406Sopenharmony_ci      if (copysize > *buf_size - copied )
1103141cc406Sopenharmony_ci        copysize = *buf_size - copied;
1104141cc406Sopenharmony_ci
1105141cc406Sopenharmony_ci      memcpy(buf, &(bc->buffer[bc->start]), copysize);
1106141cc406Sopenharmony_ci
1107141cc406Sopenharmony_ci      copied += copysize;
1108141cc406Sopenharmony_ci      buf = &buf[copysize];
1109141cc406Sopenharmony_ci
1110141cc406Sopenharmony_ci      bc->start += copysize;
1111141cc406Sopenharmony_ci      if (bc->start >= bc->used)
1112141cc406Sopenharmony_ci        {
1113141cc406Sopenharmony_ci          bc->start = 0;
1114141cc406Sopenharmony_ci          bc->shm_status = SHM_EMPTY;
1115141cc406Sopenharmony_ci          s->read_buff++;
1116141cc406Sopenharmony_ci          if (s->read_buff == s->dev->info.buffers)
1117141cc406Sopenharmony_ci            s->read_buff = 0;
1118141cc406Sopenharmony_ci          bc = &s->rdr_ctl->buf_ctl[s->read_buff];
1119141cc406Sopenharmony_ci        }
1120141cc406Sopenharmony_ci    }
1121141cc406Sopenharmony_ci
1122141cc406Sopenharmony_ci  DBG(11, ">>\n");
1123141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1124141cc406Sopenharmony_ci}
1125141cc406Sopenharmony_ci
1126141cc406Sopenharmony_ci#else /* don't USE_FORK: */
1127141cc406Sopenharmony_ci
1128141cc406Sopenharmony_cistatic SANE_Status
1129141cc406Sopenharmony_ciread_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size)
1130141cc406Sopenharmony_ci{
1131141cc406Sopenharmony_ci  static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1132141cc406Sopenharmony_ci  SANE_Status status = SANE_STATUS_GOOD;
1133141cc406Sopenharmony_ci  size_t remain = *buf_size;
1134141cc406Sopenharmony_ci  size_t nread;
1135141cc406Sopenharmony_ci  int retries = MAX_RETRIES;
1136141cc406Sopenharmony_ci  DBG (11, "<< read_data ");
1137141cc406Sopenharmony_ci
1138141cc406Sopenharmony_ci  /* sane_read_shuffled requires that read_data returns
1139141cc406Sopenharmony_ci     exactly *buf_size bytes, so it must be guaranteed here.
1140141cc406Sopenharmony_ci     Further make sure that not more bytes are read in than
1141141cc406Sopenharmony_ci     sanei_scsi_max_request_size allows, to avoid a failure
1142141cc406Sopenharmony_ci     of the read command
1143141cc406Sopenharmony_ci  */
1144141cc406Sopenharmony_ci  while (remain > 0)
1145141cc406Sopenharmony_ci    {
1146141cc406Sopenharmony_ci      nread = remain;
1147141cc406Sopenharmony_ci      if (nread > s->dev->info.bufsize)
1148141cc406Sopenharmony_ci        nread = s->dev->info.bufsize;
1149141cc406Sopenharmony_ci      cmd[6] = nread >> 16;
1150141cc406Sopenharmony_ci      cmd[7] = nread >> 8;
1151141cc406Sopenharmony_ci      cmd[8] = nread;
1152141cc406Sopenharmony_ci      status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd),
1153141cc406Sopenharmony_ci                 &buf[*buf_size - remain], &nread);
1154141cc406Sopenharmony_ci      if (status == SANE_STATUS_DEVICE_BUSY && retries)
1155141cc406Sopenharmony_ci        {
1156141cc406Sopenharmony_ci          retries--;
1157141cc406Sopenharmony_ci          nread = 0;
1158141cc406Sopenharmony_ci          usleep(10000);
1159141cc406Sopenharmony_ci        }
1160141cc406Sopenharmony_ci      else if (status != SANE_STATUS_GOOD)
1161141cc406Sopenharmony_ci        {
1162141cc406Sopenharmony_ci          DBG(11, ">>\n");
1163141cc406Sopenharmony_ci          return(status);
1164141cc406Sopenharmony_ci        }
1165141cc406Sopenharmony_ci      else
1166141cc406Sopenharmony_ci        {
1167141cc406Sopenharmony_ci          retries = MAX_RETRIES;
1168141cc406Sopenharmony_ci        }
1169141cc406Sopenharmony_ci      remain -= nread;
1170141cc406Sopenharmony_ci    }
1171141cc406Sopenharmony_ci  DBG (11, ">>\n");
1172141cc406Sopenharmony_ci  return (status);
1173141cc406Sopenharmony_ci}
1174141cc406Sopenharmony_ci#endif
1175141cc406Sopenharmony_ci
1176141cc406Sopenharmony_cistatic size_t
1177141cc406Sopenharmony_cimax_string_size (const SANE_String_Const strings[])
1178141cc406Sopenharmony_ci{
1179141cc406Sopenharmony_ci  size_t size, max_size = 0;
1180141cc406Sopenharmony_ci  int i;
1181141cc406Sopenharmony_ci  DBG (10, "<< max_string_size ");
1182141cc406Sopenharmony_ci
1183141cc406Sopenharmony_ci  for (i = 0; strings[i]; ++i)
1184141cc406Sopenharmony_ci    {
1185141cc406Sopenharmony_ci      size = strlen (strings[i]) + 1;
1186141cc406Sopenharmony_ci      if (size > max_size)
1187141cc406Sopenharmony_ci	max_size = size;
1188141cc406Sopenharmony_ci    }
1189141cc406Sopenharmony_ci
1190141cc406Sopenharmony_ci  DBG (10, ">>\n");
1191141cc406Sopenharmony_ci  return max_size;
1192141cc406Sopenharmony_ci}
1193141cc406Sopenharmony_ci
1194141cc406Sopenharmony_cistatic SANE_Status
1195141cc406Sopenharmony_ciwait_ready(int fd)
1196141cc406Sopenharmony_ci{
1197141cc406Sopenharmony_ci  SANE_Status status;
1198141cc406Sopenharmony_ci  int retry = 0;
1199141cc406Sopenharmony_ci
1200141cc406Sopenharmony_ci  while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD)
1201141cc406Sopenharmony_ci  {
1202141cc406Sopenharmony_ci    DBG (5, "wait_ready failed (%d)\n", retry);
1203141cc406Sopenharmony_ci    if (retry++ > 15){
1204141cc406Sopenharmony_ci	return SANE_STATUS_IO_ERROR;
1205141cc406Sopenharmony_ci    }
1206141cc406Sopenharmony_ci    sleep(3);
1207141cc406Sopenharmony_ci  }
1208141cc406Sopenharmony_ci  return (status);
1209141cc406Sopenharmony_ci
1210141cc406Sopenharmony_ci}
1211141cc406Sopenharmony_ci
1212141cc406Sopenharmony_ci/* ask the scanner for the maximum scan sizes with/without ADF and
1213141cc406Sopenharmony_ci   FSU. The JX330 manual does mention the sizes.
1214141cc406Sopenharmony_ci*/
1215141cc406Sopenharmony_cistatic SANE_Status
1216141cc406Sopenharmony_ciget_max_scan_size(int fd, SHARP_Device *dev, int mode)
1217141cc406Sopenharmony_ci{
1218141cc406Sopenharmony_ci  SANE_Status status;
1219141cc406Sopenharmony_ci  mode_sense_subdevice m_subdev;
1220141cc406Sopenharmony_ci  size_t buf_size;
1221141cc406Sopenharmony_ci
1222141cc406Sopenharmony_ci  status = mode_select_adf_fsu(fd, mode);
1223141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1224141cc406Sopenharmony_ci    {
1225141cc406Sopenharmony_ci      DBG (1, "get_scan_sizes: MODE_SELECT/subdevice page failed\n");
1226141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1227141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1228141cc406Sopenharmony_ci    }
1229141cc406Sopenharmony_ci
1230141cc406Sopenharmony_ci  DBG (3, "get_scan_sizes: sending MODE SENSE/subdevice page\n");
1231141cc406Sopenharmony_ci  memset (&m_subdev, 0, sizeof (m_subdev));
1232141cc406Sopenharmony_ci  buf_size = sizeof (m_subdev);
1233141cc406Sopenharmony_ci  status = mode_sense (fd, &m_subdev, &buf_size, 0x20);
1234141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1235141cc406Sopenharmony_ci    {
1236141cc406Sopenharmony_ci      DBG (1, "get_scan_sizes: MODE_SENSE/subdevice page failed\n");
1237141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1238141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1239141cc406Sopenharmony_ci    }
1240141cc406Sopenharmony_ci
1241141cc406Sopenharmony_ci  dev->info.tl_x_ranges[mode].min = 0;
1242141cc406Sopenharmony_ci  dev->info.tl_x_ranges[mode].max = SANE_FIX(PIX_TO_MM(
1243141cc406Sopenharmony_ci    (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) +
1244141cc406Sopenharmony_ci    (m_subdev.max_x[2] << 8) + m_subdev.max_x[3] - 1, dev->info.mud));
1245141cc406Sopenharmony_ci  dev->info.tl_x_ranges[mode].quant = 0;
1246141cc406Sopenharmony_ci
1247141cc406Sopenharmony_ci  dev->info.br_x_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud));
1248141cc406Sopenharmony_ci  dev->info.br_x_ranges[mode].max = SANE_FIX(PIX_TO_MM(
1249141cc406Sopenharmony_ci    (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) +
1250141cc406Sopenharmony_ci    (m_subdev.max_x[2] << 8) + m_subdev.max_x[3], dev->info.mud));
1251141cc406Sopenharmony_ci  dev->info.br_x_ranges[mode].quant = 0;
1252141cc406Sopenharmony_ci
1253141cc406Sopenharmony_ci  dev->info.tl_y_ranges[mode].min = 0;
1254141cc406Sopenharmony_ci  if ((dev->sensedat.model != JX250 && dev->sensedat.model != JX350) ||
1255141cc406Sopenharmony_ci      mode != SCAN_WITH_FSU)
1256141cc406Sopenharmony_ci    dev->info.tl_y_ranges[mode].max = SANE_FIX(PIX_TO_MM(
1257141cc406Sopenharmony_ci      (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) +
1258141cc406Sopenharmony_ci      (m_subdev.max_y[2] << 8) + m_subdev.max_y[3] - 1, dev->info.mud));
1259141cc406Sopenharmony_ci  else
1260141cc406Sopenharmony_ci    /* The manual for the JX250 states on page 62 that the maximum
1261141cc406Sopenharmony_ci       value for tl_y in FSU mode is 13199, while the max value for
1262141cc406Sopenharmony_ci       br_y is 13900, which is (probably -- I don't have a FSU) returned
1263141cc406Sopenharmony_ci       by mode sense/subdevice page. Therefore, we cannot simply
1264141cc406Sopenharmony_ci       decrement that value and store it as max(tl_y).
1265141cc406Sopenharmony_ci    */
1266141cc406Sopenharmony_ci    dev->info.tl_y_ranges[mode].max = 13199;
1267141cc406Sopenharmony_ci  dev->info.tl_y_ranges[mode].quant = 0;
1268141cc406Sopenharmony_ci
1269141cc406Sopenharmony_ci  dev->info.br_y_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud));
1270141cc406Sopenharmony_ci  dev->info.br_y_ranges[mode].max = SANE_FIX(PIX_TO_MM(
1271141cc406Sopenharmony_ci    (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) +
1272141cc406Sopenharmony_ci    (m_subdev.max_y[2] << 8) + m_subdev.max_y[3], dev->info.mud));
1273141cc406Sopenharmony_ci  dev->info.br_y_ranges[mode].quant = 0;
1274141cc406Sopenharmony_ci
1275141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1276141cc406Sopenharmony_ci}
1277141cc406Sopenharmony_ci
1278141cc406Sopenharmony_cistatic SANE_Status
1279141cc406Sopenharmony_ciattach (const char *devnam, SHARP_Device ** devp)
1280141cc406Sopenharmony_ci{
1281141cc406Sopenharmony_ci  SANE_Status status;
1282141cc406Sopenharmony_ci  SHARP_Device *dev;
1283141cc406Sopenharmony_ci  SHARP_Sense_Data sensedat;
1284141cc406Sopenharmony_ci
1285141cc406Sopenharmony_ci  int fd;
1286141cc406Sopenharmony_ci  char inquiry_data[INQUIRY_LEN];
1287141cc406Sopenharmony_ci  const char *model_name;
1288141cc406Sopenharmony_ci  mode_sense_param msp;
1289141cc406Sopenharmony_ci  mode_sense_subdevice m_subdev;
1290141cc406Sopenharmony_ci  size_t buf_size;
1291141cc406Sopenharmony_ci  DBG (10, "<< attach ");
1292141cc406Sopenharmony_ci
1293141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
1294141cc406Sopenharmony_ci    {
1295141cc406Sopenharmony_ci      if (strcmp (dev->sane.name, devnam) == 0)
1296141cc406Sopenharmony_ci	{
1297141cc406Sopenharmony_ci	  if (devp)
1298141cc406Sopenharmony_ci	    *devp = dev;
1299141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
1300141cc406Sopenharmony_ci	}
1301141cc406Sopenharmony_ci    }
1302141cc406Sopenharmony_ci
1303141cc406Sopenharmony_ci  sensedat.model = unknown;
1304141cc406Sopenharmony_ci  sensedat.complain_on_errors = 0;
1305141cc406Sopenharmony_ci  DBG (3, "attach: opening %s\n", devnam);
1306141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
1307141cc406Sopenharmony_ci  {
1308141cc406Sopenharmony_ci    int bufsize = 4096;
1309141cc406Sopenharmony_ci    status = sanei_scsi_open_extended (devnam, &fd, &sense_handler, &sensedat, &bufsize);
1310141cc406Sopenharmony_ci    if (status != SANE_STATUS_GOOD)
1311141cc406Sopenharmony_ci      {
1312141cc406Sopenharmony_ci        DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
1313141cc406Sopenharmony_ci        return (status);
1314141cc406Sopenharmony_ci      }
1315141cc406Sopenharmony_ci    if (bufsize < 4096)
1316141cc406Sopenharmony_ci      {
1317141cc406Sopenharmony_ci        DBG(1, "attach: open failed. no memory\n");
1318141cc406Sopenharmony_ci        sanei_scsi_close(fd);
1319141cc406Sopenharmony_ci        return SANE_STATUS_NO_MEM;
1320141cc406Sopenharmony_ci      }
1321141cc406Sopenharmony_ci  }
1322141cc406Sopenharmony_ci#else
1323141cc406Sopenharmony_ci  status = sanei_scsi_open (devnam, &fd, &sense_handler, &sensedat);
1324141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1325141cc406Sopenharmony_ci    {
1326141cc406Sopenharmony_ci      DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
1327141cc406Sopenharmony_ci      return (status);
1328141cc406Sopenharmony_ci    }
1329141cc406Sopenharmony_ci#endif
1330141cc406Sopenharmony_ci
1331141cc406Sopenharmony_ci  DBG (3, "attach: sending INQUIRY\n");
1332141cc406Sopenharmony_ci  memset (inquiry_data, 0, sizeof (inquiry_data));
1333141cc406Sopenharmony_ci  buf_size = sizeof (inquiry_data);
1334141cc406Sopenharmony_ci  status = inquiry (fd, inquiry_data, &buf_size);
1335141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1336141cc406Sopenharmony_ci    {
1337141cc406Sopenharmony_ci      DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status));
1338141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1339141cc406Sopenharmony_ci      return (status);
1340141cc406Sopenharmony_ci    }
1341141cc406Sopenharmony_ci
1342141cc406Sopenharmony_ci  if (inquiry_data[0] == 6 && strncmp (inquiry_data + 8, "SHARP", 5) == 0)
1343141cc406Sopenharmony_ci    {
1344141cc406Sopenharmony_ci      if (strncmp (inquiry_data + 16, "JX610", 5) == 0)
1345141cc406Sopenharmony_ci        sensedat.model = JX610;
1346141cc406Sopenharmony_ci      else if (strncmp (inquiry_data + 16, "JX250", 5) == 0)
1347141cc406Sopenharmony_ci        sensedat.model = JX250;
1348141cc406Sopenharmony_ci      else if (strncmp (inquiry_data + 16, "JX350", 5) == 0)
1349141cc406Sopenharmony_ci        sensedat.model = JX350;
1350141cc406Sopenharmony_ci      else if (   strncmp (inquiry_data + 16, "JX320", 5) == 0
1351141cc406Sopenharmony_ci               || strncmp (inquiry_data + 16, "JX325", 5) == 0)
1352141cc406Sopenharmony_ci        sensedat.model = JX320;
1353141cc406Sopenharmony_ci      else if (strncmp (inquiry_data + 16, "JX330", 5) == 0)
1354141cc406Sopenharmony_ci        sensedat.model = JX330;
1355141cc406Sopenharmony_ci    }
1356141cc406Sopenharmony_ci
1357141cc406Sopenharmony_ci  if (sensedat.model == unknown)
1358141cc406Sopenharmony_ci    {
1359141cc406Sopenharmony_ci      DBG (1, "attach: device doesn't look like a Sharp scanner\n");
1360141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1361141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1362141cc406Sopenharmony_ci    }
1363141cc406Sopenharmony_ci
1364141cc406Sopenharmony_ci  DBG (3, "attach: sending TEST_UNIT_READY\n");
1365141cc406Sopenharmony_ci  status = test_unit_ready (fd);
1366141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1367141cc406Sopenharmony_ci    {
1368141cc406Sopenharmony_ci      DBG (1, "attach: test unit ready failed (%s)\n",
1369141cc406Sopenharmony_ci	   sane_strstatus (status));
1370141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1371141cc406Sopenharmony_ci      return (status);
1372141cc406Sopenharmony_ci    }
1373141cc406Sopenharmony_ci
1374141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SELECT\n");
1375141cc406Sopenharmony_ci  /* JX-610 probably supports only 25 MUD size
1376141cc406Sopenharmony_ci     JX-320 only supports 25 MUD size
1377141cc406Sopenharmony_ci  */
1378141cc406Sopenharmony_ci  if (strncmp (inquiry_data + 16, "JX610", 5) == 0)
1379141cc406Sopenharmony_ci    status = mode_select_mud (fd, DEFAULT_MUD_JX610);
1380141cc406Sopenharmony_ci  else if (strncmp (inquiry_data + 16, "JX320", 5) == 0)
1381141cc406Sopenharmony_ci    status = mode_select_mud (fd, DEFAULT_MUD_JX320);
1382141cc406Sopenharmony_ci  else
1383141cc406Sopenharmony_ci    status = mode_select_mud (fd, DEFAULT_MUD_JX330);
1384141cc406Sopenharmony_ci
1385141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1386141cc406Sopenharmony_ci    {
1387141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SELECT6 failed\n");
1388141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1389141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1390141cc406Sopenharmony_ci    }
1391141cc406Sopenharmony_ci
1392141cc406Sopenharmony_ci  DBG (3, "attach: sending MODE SENSE/MUP page\n");
1393141cc406Sopenharmony_ci  memset (&msp, 0, sizeof (msp));
1394141cc406Sopenharmony_ci  buf_size = sizeof (msp);
1395141cc406Sopenharmony_ci  status = mode_sense (fd, &msp, &buf_size, 3);
1396141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
1397141cc406Sopenharmony_ci    {
1398141cc406Sopenharmony_ci      DBG (1, "attach: MODE_SENSE/MUP page failed\n");
1399141cc406Sopenharmony_ci      sanei_scsi_close (fd);
1400141cc406Sopenharmony_ci      return (SANE_STATUS_INVAL);
1401141cc406Sopenharmony_ci    }
1402141cc406Sopenharmony_ci
1403141cc406Sopenharmony_ci  dev = malloc (sizeof (*dev));
1404141cc406Sopenharmony_ci  if (!dev)
1405141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
1406141cc406Sopenharmony_ci  memset (dev, 0, sizeof (*dev));
1407141cc406Sopenharmony_ci
1408141cc406Sopenharmony_ci  dev->sane.name = strdup (devnam);
1409141cc406Sopenharmony_ci  dev->sane.vendor = "SHARP";
1410141cc406Sopenharmony_ci  model_name = (char*) inquiry_data + 16;
1411141cc406Sopenharmony_ci  dev->sane.model  = strndup (model_name, 10);
1412141cc406Sopenharmony_ci  dev->sane.type = "flatbed scanner";
1413141cc406Sopenharmony_ci
1414141cc406Sopenharmony_ci  dev->sensedat.model = sensedat.model;
1415141cc406Sopenharmony_ci
1416141cc406Sopenharmony_ci  DBG (5, "dev->sane.name = %s\n", dev->sane.name);
1417141cc406Sopenharmony_ci  DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor);
1418141cc406Sopenharmony_ci  DBG (5, "dev->sane.model = %s\n", dev->sane.model);
1419141cc406Sopenharmony_ci  DBG (5, "dev->sane.type = %s\n", dev->sane.type);
1420141cc406Sopenharmony_ci
1421141cc406Sopenharmony_ci  dev->info.xres_range.quant = 0;
1422141cc406Sopenharmony_ci  dev->info.yres_range.quant = 0;
1423141cc406Sopenharmony_ci
1424141cc406Sopenharmony_ci  dev->info.tl_x_ranges[SCAN_SIMPLE].min = SANE_FIX(0);
1425141cc406Sopenharmony_ci  dev->info.br_x_ranges[SCAN_SIMPLE].min = SANE_FIX(1);
1426141cc406Sopenharmony_ci  dev->info.tl_y_ranges[SCAN_SIMPLE].min = SANE_FIX(0);
1427141cc406Sopenharmony_ci  dev->info.br_y_ranges[SCAN_SIMPLE].min = SANE_FIX(1);
1428141cc406Sopenharmony_ci  dev->info.tl_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0);
1429141cc406Sopenharmony_ci  dev->info.br_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0);
1430141cc406Sopenharmony_ci  dev->info.tl_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0);
1431141cc406Sopenharmony_ci  dev->info.br_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0);
1432141cc406Sopenharmony_ci
1433141cc406Sopenharmony_ci  dev->info.xres_default = 150;
1434141cc406Sopenharmony_ci  dev->info.yres_default = 150;
1435141cc406Sopenharmony_ci  dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(209);
1436141cc406Sopenharmony_ci  dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210);
1437141cc406Sopenharmony_ci  dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(296);
1438141cc406Sopenharmony_ci  dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297);
1439141cc406Sopenharmony_ci
1440141cc406Sopenharmony_ci  dev->info.bmu = msp.bmu;
1441141cc406Sopenharmony_ci  dev->info.mud = (msp.mud[0] << 8) + msp.mud[1];
1442141cc406Sopenharmony_ci
1443141cc406Sopenharmony_ci  dev->info.adf_fsu_installed = 0;
1444141cc406Sopenharmony_ci  if (dev->sensedat.model == JX610)
1445141cc406Sopenharmony_ci    {
1446141cc406Sopenharmony_ci      dev->info.xres_range.max = 600;
1447141cc406Sopenharmony_ci      dev->info.xres_range.min = 30;
1448141cc406Sopenharmony_ci
1449141cc406Sopenharmony_ci      dev->info.yres_range.max = 600;
1450141cc406Sopenharmony_ci      dev->info.yres_range.min = 30;
1451141cc406Sopenharmony_ci      dev->info.x_default = SANE_FIX(210);
1452141cc406Sopenharmony_ci      dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(303); /* 304.8mm is the real max */
1453141cc406Sopenharmony_ci      dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(304); /* 304.8mm is the real max */
1454141cc406Sopenharmony_ci
1455141cc406Sopenharmony_ci      dev->info.y_default = SANE_FIX(297);
1456141cc406Sopenharmony_ci      dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(430); /* 431.8 is the real max */
1457141cc406Sopenharmony_ci      dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(431); /* 431.8 is the real max */
1458141cc406Sopenharmony_ci    }
1459141cc406Sopenharmony_ci  else if (dev->sensedat.model == JX320)
1460141cc406Sopenharmony_ci    {
1461141cc406Sopenharmony_ci      dev->info.xres_range.max = 600;
1462141cc406Sopenharmony_ci      dev->info.xres_range.min = 30;
1463141cc406Sopenharmony_ci
1464141cc406Sopenharmony_ci      dev->info.yres_range.max = 600;
1465141cc406Sopenharmony_ci      dev->info.yres_range.min = 30;
1466141cc406Sopenharmony_ci      dev->info.x_default = SANE_FIX(210);
1467141cc406Sopenharmony_ci      dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(212);
1468141cc406Sopenharmony_ci      dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(213);
1469141cc406Sopenharmony_ci
1470141cc406Sopenharmony_ci      dev->info.y_default = SANE_FIX(297);
1471141cc406Sopenharmony_ci      dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(292);
1472141cc406Sopenharmony_ci      dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(293);
1473141cc406Sopenharmony_ci    }
1474141cc406Sopenharmony_ci  else
1475141cc406Sopenharmony_ci    {
1476141cc406Sopenharmony_ci      /* ask the scanner, if ADF or FSU are installed, and ask for
1477141cc406Sopenharmony_ci         the maximum scan sizes with/without ADF and FSU.
1478141cc406Sopenharmony_ci      */
1479141cc406Sopenharmony_ci
1480141cc406Sopenharmony_ci      DBG (3, "attach: sending MODE SENSE/subdevice page\n");
1481141cc406Sopenharmony_ci      memset (&m_subdev, 0, sizeof (m_subdev));
1482141cc406Sopenharmony_ci      buf_size = sizeof (m_subdev);
1483141cc406Sopenharmony_ci      status = mode_sense (fd, &m_subdev, &buf_size, 0x20);
1484141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
1485141cc406Sopenharmony_ci        {
1486141cc406Sopenharmony_ci          DBG (1, "attach: MODE_SENSE/subdevice page failed\n");
1487141cc406Sopenharmony_ci          sanei_scsi_close (fd);
1488141cc406Sopenharmony_ci          return (SANE_STATUS_INVAL);
1489141cc406Sopenharmony_ci        }
1490141cc406Sopenharmony_ci
1491141cc406Sopenharmony_ci      /* The JX330 manual is not very clear about the ADF- und FSU-Bits
1492141cc406Sopenharmony_ci         returned by a JX320 and JX325 for the mode sense command:
1493141cc406Sopenharmony_ci         Are these bits set to zero or not? To be on the safe side, let's
1494141cc406Sopenharmony_ci         clear them.
1495141cc406Sopenharmony_ci      */
1496141cc406Sopenharmony_ci
1497141cc406Sopenharmony_ci      if (   strncmp(inquiry_data + 16, "JX320", 5) == 0
1498141cc406Sopenharmony_ci          || strncmp(inquiry_data + 16, "JX325", 5) == 0)
1499141cc406Sopenharmony_ci        {
1500141cc406Sopenharmony_ci          m_subdev.f_mode_type = 0;
1501141cc406Sopenharmony_ci          m_subdev.a_mode_type = 0;
1502141cc406Sopenharmony_ci        }
1503141cc406Sopenharmony_ci
1504141cc406Sopenharmony_ci      get_max_scan_size(fd, dev, SCAN_SIMPLE);
1505141cc406Sopenharmony_ci
1506141cc406Sopenharmony_ci      if (m_subdev.a_mode_type & 0x03)
1507141cc406Sopenharmony_ci        {
1508141cc406Sopenharmony_ci          dev->info.adf_fsu_installed = HAVE_ADF;
1509141cc406Sopenharmony_ci          get_max_scan_size(fd, dev, SCAN_WITH_ADF);
1510141cc406Sopenharmony_ci        }
1511141cc406Sopenharmony_ci      if (m_subdev.f_mode_type & 0x07)
1512141cc406Sopenharmony_ci        {
1513141cc406Sopenharmony_ci          dev->info.adf_fsu_installed |= HAVE_FSU;
1514141cc406Sopenharmony_ci          get_max_scan_size(fd, dev, SCAN_WITH_FSU);
1515141cc406Sopenharmony_ci        }
1516141cc406Sopenharmony_ci
1517141cc406Sopenharmony_ci      if (   dev->sensedat.model == JX320
1518141cc406Sopenharmony_ci          || dev->sensedat.model == JX330
1519141cc406Sopenharmony_ci          || dev->sensedat.model == JX350)
1520141cc406Sopenharmony_ci        {
1521141cc406Sopenharmony_ci          dev->info.xres_range.max = 600;
1522141cc406Sopenharmony_ci          dev->info.xres_range.min = 30;
1523141cc406Sopenharmony_ci
1524141cc406Sopenharmony_ci          dev->info.yres_range.max = 600;
1525141cc406Sopenharmony_ci          dev->info.yres_range.min = 30;
1526141cc406Sopenharmony_ci          dev->info.x_default = SANE_FIX(210);
1527141cc406Sopenharmony_ci          dev->info.y_default = SANE_FIX(297);
1528141cc406Sopenharmony_ci        }
1529141cc406Sopenharmony_ci      else if (dev->sensedat.model == JX250)
1530141cc406Sopenharmony_ci        {
1531141cc406Sopenharmony_ci          dev->info.xres_range.max = 400;
1532141cc406Sopenharmony_ci          dev->info.xres_range.min = 30;
1533141cc406Sopenharmony_ci
1534141cc406Sopenharmony_ci          dev->info.yres_range.max = 400;
1535141cc406Sopenharmony_ci          dev->info.yres_range.min = 30;
1536141cc406Sopenharmony_ci          dev->info.x_default = SANE_FIX(210);
1537141cc406Sopenharmony_ci          dev->info.y_default = SANE_FIX(297);
1538141cc406Sopenharmony_ci        }
1539141cc406Sopenharmony_ci    }
1540141cc406Sopenharmony_ci  sanei_scsi_close (fd);
1541141cc406Sopenharmony_ci
1542141cc406Sopenharmony_ci  dev->info.threshold_range.min = 1;
1543141cc406Sopenharmony_ci  dev->info.threshold_range.max = 255;
1544141cc406Sopenharmony_ci  dev->info.threshold_range.quant = 0;
1545141cc406Sopenharmony_ci
1546141cc406Sopenharmony_ci  DBG (5, "xres_default=%d\n", dev->info.xres_default);
1547141cc406Sopenharmony_ci  DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max);
1548141cc406Sopenharmony_ci  DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min);
1549141cc406Sopenharmony_ci  DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant);
1550141cc406Sopenharmony_ci  DBG (5, "yres_default=%d\n", dev->info.yres_default);
1551141cc406Sopenharmony_ci  DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max);
1552141cc406Sopenharmony_ci  DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min);
1553141cc406Sopenharmony_ci  DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant);
1554141cc406Sopenharmony_ci
1555141cc406Sopenharmony_ci  DBG (5, "x_default=%f\n", SANE_UNFIX(dev->info.x_default));
1556141cc406Sopenharmony_ci  DBG (5, "tl_x_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].max));
1557141cc406Sopenharmony_ci  DBG (5, "tl_x_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].min));
1558141cc406Sopenharmony_ci  DBG (5, "tl_x_range[0].quant=%d\n", dev->info.tl_x_ranges[SCAN_SIMPLE].quant);
1559141cc406Sopenharmony_ci  DBG (5, "br_x_range[0].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].max));
1560141cc406Sopenharmony_ci  DBG (5, "br_x_range[0].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].min));
1561141cc406Sopenharmony_ci  DBG (5, "br_x_range[0].quant=%d\n", dev->info.br_x_ranges[SCAN_SIMPLE].quant);
1562141cc406Sopenharmony_ci  DBG (5, "y_default=%f\n", SANE_UNFIX(dev->info.y_default));
1563141cc406Sopenharmony_ci  DBG (5, "tl_y_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].max));
1564141cc406Sopenharmony_ci  DBG (5, "tl_y_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].min));
1565141cc406Sopenharmony_ci  DBG (5, "tl_y_range[0].quant=%d\n", dev->info.tl_y_ranges[SCAN_SIMPLE].quant);
1566141cc406Sopenharmony_ci  DBG (5, "br_y_range[0].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].max));
1567141cc406Sopenharmony_ci  DBG (5, "br_y_range[0].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].min));
1568141cc406Sopenharmony_ci  DBG (5, "br_y_range[0].quant=%d\n", dev->info.br_y_ranges[SCAN_SIMPLE].quant);
1569141cc406Sopenharmony_ci
1570141cc406Sopenharmony_ci  if (dev->info.adf_fsu_installed & HAVE_FSU)
1571141cc406Sopenharmony_ci    {
1572141cc406Sopenharmony_ci      DBG (5, "tl_x_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].max));
1573141cc406Sopenharmony_ci      DBG (5, "tl_x_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].min));
1574141cc406Sopenharmony_ci      DBG (5, "tl_x_range[1].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_FSU].quant);
1575141cc406Sopenharmony_ci      DBG (5, "br_x_range[1].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].max));
1576141cc406Sopenharmony_ci      DBG (5, "br_x_range[1].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].min));
1577141cc406Sopenharmony_ci      DBG (5, "br_x_range[1].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_FSU].quant);
1578141cc406Sopenharmony_ci      DBG (5, "tl_y_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].max));
1579141cc406Sopenharmony_ci      DBG (5, "tl_y_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].min));
1580141cc406Sopenharmony_ci      DBG (5, "tl_y_range[1].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_FSU].quant);
1581141cc406Sopenharmony_ci      DBG (5, "br_y_range[1].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].max));
1582141cc406Sopenharmony_ci      DBG (5, "br_y_range[1].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].min));
1583141cc406Sopenharmony_ci      DBG (5, "br_y_range[1].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_FSU].quant);
1584141cc406Sopenharmony_ci    }
1585141cc406Sopenharmony_ci
1586141cc406Sopenharmony_ci  if (dev->info.adf_fsu_installed & HAVE_ADF)
1587141cc406Sopenharmony_ci    {
1588141cc406Sopenharmony_ci      DBG (5, "tl_x_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].max));
1589141cc406Sopenharmony_ci      DBG (5, "tl_x_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].min));
1590141cc406Sopenharmony_ci      DBG (5, "tl_x_range[2].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_ADF].quant);
1591141cc406Sopenharmony_ci      DBG (5, "br_x_range[2].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].max));
1592141cc406Sopenharmony_ci      DBG (5, "br_x_range[2].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].min));
1593141cc406Sopenharmony_ci      DBG (5, "br_x_range[2].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_ADF].quant);
1594141cc406Sopenharmony_ci      DBG (5, "tl_y_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].max));
1595141cc406Sopenharmony_ci      DBG (5, "tl_y_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].min));
1596141cc406Sopenharmony_ci      DBG (5, "tl_y_range[2].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_ADF].quant);
1597141cc406Sopenharmony_ci      DBG (5, "br_y_range[2].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].max));
1598141cc406Sopenharmony_ci      DBG (5, "br_y_range[2].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].min));
1599141cc406Sopenharmony_ci      DBG (5, "br_y_range[2].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_ADF].quant);
1600141cc406Sopenharmony_ci    }
1601141cc406Sopenharmony_ci
1602141cc406Sopenharmony_ci  DBG (5, "bmu=%d\n", dev->info.bmu);
1603141cc406Sopenharmony_ci  DBG (5, "mud=%d\n", dev->info.mud);
1604141cc406Sopenharmony_ci
1605141cc406Sopenharmony_ci  ++num_devices;
1606141cc406Sopenharmony_ci  dev->next = first_dev;
1607141cc406Sopenharmony_ci  first_dev = dev;
1608141cc406Sopenharmony_ci
1609141cc406Sopenharmony_ci  if (devp)
1610141cc406Sopenharmony_ci    *devp = dev;
1611141cc406Sopenharmony_ci
1612141cc406Sopenharmony_ci  DBG (10, ">>\n");
1613141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
1614141cc406Sopenharmony_ci}
1615141cc406Sopenharmony_ci
1616141cc406Sopenharmony_ci/* Enabling / disabling of gamma options.
1617141cc406Sopenharmony_ci   Depends on many user settable options, so lets put it into
1618141cc406Sopenharmony_ci   one function to be called by init_options and by sane_control_option
1619141cc406Sopenharmony_ci
1620141cc406Sopenharmony_ci*/
1621141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
1622141cc406Sopenharmony_cistatic void
1623141cc406Sopenharmony_ciset_gamma_caps(SHARP_Scanner *s)
1624141cc406Sopenharmony_ci{
1625141cc406Sopenharmony_ci  /* neither fixed nor custom gamma for line art modes */
1626141cc406Sopenharmony_ci  if (   strcmp(s->val[OPT_MODE].s, M_LINEART) == 0
1627141cc406Sopenharmony_ci      || strcmp(s->val[OPT_MODE].s, M_LINEART_COLOR) == 0)
1628141cc406Sopenharmony_ci    {
1629141cc406Sopenharmony_ci      s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE;
1630141cc406Sopenharmony_ci      s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
1631141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
1632141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
1633141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1634141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1635141cc406Sopenharmony_ci    }
1636141cc406Sopenharmony_ci  else if (strcmp(s->val[OPT_MODE].s, M_GRAY) == 0)
1637141cc406Sopenharmony_ci    {
1638141cc406Sopenharmony_ci      s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1639141cc406Sopenharmony_ci      if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE)
1640141cc406Sopenharmony_ci        {
1641141cc406Sopenharmony_ci          s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1642141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
1643141cc406Sopenharmony_ci        }
1644141cc406Sopenharmony_ci      else
1645141cc406Sopenharmony_ci        {
1646141cc406Sopenharmony_ci          s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE;
1647141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
1648141cc406Sopenharmony_ci        }
1649141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
1650141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1651141cc406Sopenharmony_ci      s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1652141cc406Sopenharmony_ci    }
1653141cc406Sopenharmony_ci  else
1654141cc406Sopenharmony_ci    {
1655141cc406Sopenharmony_ci      /* color mode */
1656141cc406Sopenharmony_ci      s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1657141cc406Sopenharmony_ci      if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE)
1658141cc406Sopenharmony_ci        {
1659141cc406Sopenharmony_ci          s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE;
1660141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR].cap   |= SANE_CAP_INACTIVE;
1661141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
1662141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1663141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1664141cc406Sopenharmony_ci        }
1665141cc406Sopenharmony_ci      else
1666141cc406Sopenharmony_ci        {
1667141cc406Sopenharmony_ci          s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE;
1668141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR].cap   |= SANE_CAP_INACTIVE;
1669141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
1670141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
1671141cc406Sopenharmony_ci          s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
1672141cc406Sopenharmony_ci        }
1673141cc406Sopenharmony_ci    }
1674141cc406Sopenharmony_ci}
1675141cc406Sopenharmony_ci#endif /* USE_CUSTOM_GAMMA */
1676141cc406Sopenharmony_ci
1677141cc406Sopenharmony_ci/* The next function is a slightly modified version of sanei_constrain_value
1678141cc406Sopenharmony_ci   Instead of returning status information like STATUS_INVAL, it adjusts
1679141cc406Sopenharmony_ci   an invalid value to the nearest allowed one.
1680141cc406Sopenharmony_ci*/
1681141cc406Sopenharmony_cistatic void
1682141cc406Sopenharmony_ciclip_value (const SANE_Option_Descriptor * opt, void * value)
1683141cc406Sopenharmony_ci{
1684141cc406Sopenharmony_ci  const SANE_String_Const * string_list;
1685141cc406Sopenharmony_ci  const SANE_Word * word_list;
1686141cc406Sopenharmony_ci  int i, num_matches, match;
1687141cc406Sopenharmony_ci  const SANE_Range * range;
1688141cc406Sopenharmony_ci  SANE_Word w, v;
1689141cc406Sopenharmony_ci  size_t len;
1690141cc406Sopenharmony_ci
1691141cc406Sopenharmony_ci  switch (opt->constraint_type)
1692141cc406Sopenharmony_ci    {
1693141cc406Sopenharmony_ci    case SANE_CONSTRAINT_RANGE:
1694141cc406Sopenharmony_ci      w = *(SANE_Word *) value;
1695141cc406Sopenharmony_ci      range = opt->constraint.range;
1696141cc406Sopenharmony_ci
1697141cc406Sopenharmony_ci      if (w < range->min)
1698141cc406Sopenharmony_ci        w = range->min;
1699141cc406Sopenharmony_ci      else if (w > range->max)
1700141cc406Sopenharmony_ci	w = range->max;
1701141cc406Sopenharmony_ci
1702141cc406Sopenharmony_ci      if (range->quant)
1703141cc406Sopenharmony_ci	{
1704141cc406Sopenharmony_ci	  v = (w - range->min + range->quant/2) / range->quant;
1705141cc406Sopenharmony_ci	  w = v * range->quant + range->min;
1706141cc406Sopenharmony_ci	  *(SANE_Word*) value = w;
1707141cc406Sopenharmony_ci	}
1708141cc406Sopenharmony_ci      break;
1709141cc406Sopenharmony_ci
1710141cc406Sopenharmony_ci    case SANE_CONSTRAINT_WORD_LIST:
1711141cc406Sopenharmony_ci      w = *(SANE_Word *) value;
1712141cc406Sopenharmony_ci      word_list = opt->constraint.word_list;
1713141cc406Sopenharmony_ci      for (i = 1; w != word_list[i]; ++i)
1714141cc406Sopenharmony_ci	if (i >= word_list[0])
1715141cc406Sopenharmony_ci	  /* somewhat arbitrary... Would be better to have a default value
1716141cc406Sopenharmony_ci	     explicitly defined.
1717141cc406Sopenharmony_ci	  */
1718141cc406Sopenharmony_ci	  *(SANE_Word*) value = word_list[1];
1719141cc406Sopenharmony_ci      break;
1720141cc406Sopenharmony_ci
1721141cc406Sopenharmony_ci    case SANE_CONSTRAINT_STRING_LIST:
1722141cc406Sopenharmony_ci      /* Matching algorithm: take the longest unique match ignoring
1723141cc406Sopenharmony_ci	 case.  If there is an exact match, it is admissible even if
1724141cc406Sopenharmony_ci	 the same string is a prefix of a longer option name. */
1725141cc406Sopenharmony_ci      string_list = opt->constraint.string_list;
1726141cc406Sopenharmony_ci      len = strlen (value);
1727141cc406Sopenharmony_ci
1728141cc406Sopenharmony_ci      /* count how many matches of length LEN characters we have: */
1729141cc406Sopenharmony_ci      num_matches = 0;
1730141cc406Sopenharmony_ci      match = -1;
1731141cc406Sopenharmony_ci      for (i = 0; string_list[i]; ++i)
1732141cc406Sopenharmony_ci	if (strncasecmp (value, string_list[i], len) == 0
1733141cc406Sopenharmony_ci	    && len <= strlen (string_list[i]))
1734141cc406Sopenharmony_ci	  {
1735141cc406Sopenharmony_ci	    match = i;
1736141cc406Sopenharmony_ci	    if (len == strlen (string_list[i]))
1737141cc406Sopenharmony_ci	      {
1738141cc406Sopenharmony_ci		/* exact match... */
1739141cc406Sopenharmony_ci		if (strcmp (value, string_list[i]) != 0)
1740141cc406Sopenharmony_ci		  /* ...but case differs */
1741141cc406Sopenharmony_ci		  strcpy (value, string_list[match]);
1742141cc406Sopenharmony_ci	      }
1743141cc406Sopenharmony_ci	    ++num_matches;
1744141cc406Sopenharmony_ci	  }
1745141cc406Sopenharmony_ci
1746141cc406Sopenharmony_ci      if (num_matches > 1)
1747141cc406Sopenharmony_ci        /* xxx quite arbitrary... We could also choose the first match
1748141cc406Sopenharmony_ci        */
1749141cc406Sopenharmony_ci        strcpy(value, string_list[match]);
1750141cc406Sopenharmony_ci      else if (num_matches == 1)
1751141cc406Sopenharmony_ci        strcpy (value, string_list[match]);
1752141cc406Sopenharmony_ci      else
1753141cc406Sopenharmony_ci        strcpy (value, string_list[0]);
1754141cc406Sopenharmony_ci
1755141cc406Sopenharmony_ci    default:
1756141cc406Sopenharmony_ci      break;
1757141cc406Sopenharmony_ci    }
1758141cc406Sopenharmony_ci}
1759141cc406Sopenharmony_ci
1760141cc406Sopenharmony_ci/* make sure that enough memory is allocated for each string,
1761141cc406Sopenharmony_ci   so that the strcpy in sane_control_option / set value cannot
1762141cc406Sopenharmony_ci   write behind the end of the allocated memory.
1763141cc406Sopenharmony_ci*/
1764141cc406Sopenharmony_cistatic SANE_Status
1765141cc406Sopenharmony_ciinit_string_option(SHARP_Scanner *s, SANE_String_Const name,
1766141cc406Sopenharmony_ci   SANE_String_Const title, SANE_String_Const desc,
1767141cc406Sopenharmony_ci   const SANE_String_Const *string_list, int option, int default_index)
1768141cc406Sopenharmony_ci{
1769141cc406Sopenharmony_ci  int i;
1770141cc406Sopenharmony_ci
1771141cc406Sopenharmony_ci  s->opt[option].name = name;
1772141cc406Sopenharmony_ci  s->opt[option].title = title;
1773141cc406Sopenharmony_ci  s->opt[option].desc = desc;
1774141cc406Sopenharmony_ci  s->opt[option].type = SANE_TYPE_STRING;
1775141cc406Sopenharmony_ci  s->opt[option].size = max_string_size (string_list);
1776141cc406Sopenharmony_ci  s->opt[option].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1777141cc406Sopenharmony_ci  s->opt[option].constraint.string_list = string_list;
1778141cc406Sopenharmony_ci  s->val[option].s = malloc(s->opt[option].size);
1779141cc406Sopenharmony_ci  if (s->val[option].s == 0)
1780141cc406Sopenharmony_ci    {
1781141cc406Sopenharmony_ci      for (i = 1; i < NUM_OPTIONS; i++)
1782141cc406Sopenharmony_ci        {
1783141cc406Sopenharmony_ci          if (s->val[i].s && s->opt[i].type == SANE_TYPE_STRING)
1784141cc406Sopenharmony_ci            free(s->val[i].s);
1785141cc406Sopenharmony_ci        }
1786141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
1787141cc406Sopenharmony_ci    }
1788141cc406Sopenharmony_ci  strcpy(s->val[option].s, string_list[default_index]);
1789141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
1790141cc406Sopenharmony_ci}
1791141cc406Sopenharmony_ci
1792141cc406Sopenharmony_cistatic SANE_Status
1793141cc406Sopenharmony_ciinit_options (SHARP_Scanner * s)
1794141cc406Sopenharmony_ci{
1795141cc406Sopenharmony_ci  int i, default_source, sourcename_index = 0;
1796141cc406Sopenharmony_ci  SANE_Word scalar;
1797141cc406Sopenharmony_ci  DBG (10, "<< init_options ");
1798141cc406Sopenharmony_ci
1799141cc406Sopenharmony_ci  memset (s->opt, 0, sizeof (s->opt));
1800141cc406Sopenharmony_ci  memset (s->val, 0, sizeof (s->val));
1801141cc406Sopenharmony_ci
1802141cc406Sopenharmony_ci  for (i = 0; i < NUM_OPTIONS; ++i)
1803141cc406Sopenharmony_ci    {
1804141cc406Sopenharmony_ci      s->opt[i].size = sizeof (SANE_Word);
1805141cc406Sopenharmony_ci      s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
1806141cc406Sopenharmony_ci      s->val[i].s = 0;
1807141cc406Sopenharmony_ci    }
1808141cc406Sopenharmony_ci
1809141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
1810141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
1811141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
1812141cc406Sopenharmony_ci  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
1813141cc406Sopenharmony_ci  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
1814141cc406Sopenharmony_ci
1815141cc406Sopenharmony_ci  /* Mode group: */
1816141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].title = "Scan Mode";
1817141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].desc = "";
1818141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
1819141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].cap = 0;
1820141cc406Sopenharmony_ci  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1821141cc406Sopenharmony_ci
1822141cc406Sopenharmony_ci  /* scan mode */
1823141cc406Sopenharmony_ci#if 0
1824141cc406Sopenharmony_ci  s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
1825141cc406Sopenharmony_ci  s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
1826141cc406Sopenharmony_ci  s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
1827141cc406Sopenharmony_ci  s->opt[OPT_MODE].type = SANE_TYPE_STRING;
1828141cc406Sopenharmony_ci  s->opt[OPT_MODE].size = max_string_size (mode_list);
1829141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1830141cc406Sopenharmony_ci  s->opt[OPT_MODE].constraint.string_list = mode_list;
1831141cc406Sopenharmony_ci  s->val[OPT_MODE].s = strdup (mode_list[3]); /* color scan */
1832141cc406Sopenharmony_ci#endif
1833141cc406Sopenharmony_ci  init_string_option(s, SANE_NAME_SCAN_MODE, SANE_TITLE_SCAN_MODE,
1834141cc406Sopenharmony_ci    SANE_DESC_SCAN_MODE, mode_list, OPT_MODE, 3);
1835141cc406Sopenharmony_ci
1836141cc406Sopenharmony_ci  /* half tone */
1837141cc406Sopenharmony_ci#if 0
1838141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE_PATTERN;
1839141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE_PATTERN;
1840141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].desc = SANE_DESC_HALFTONE " (JX-330 only)";
1841141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING;
1842141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].size = max_string_size (halftone_list);
1843141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1844141cc406Sopenharmony_ci  s->opt[OPT_HALFTONE].constraint.string_list = halftone_list;
1845141cc406Sopenharmony_ci  s->val[OPT_HALFTONE].s = strdup (halftone_list[0]);
1846141cc406Sopenharmony_ci#endif
1847141cc406Sopenharmony_ci  init_string_option(s, SANE_NAME_HALFTONE_PATTERN, SANE_TITLE_HALFTONE_PATTERN,
1848141cc406Sopenharmony_ci    SANE_DESC_HALFTONE " (JX-330 only)", halftone_list, OPT_HALFTONE, 0);
1849141cc406Sopenharmony_ci
1850141cc406Sopenharmony_ci  if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350 ||
1851141cc406Sopenharmony_ci      s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX320)
1852141cc406Sopenharmony_ci    s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
1853141cc406Sopenharmony_ci
1854141cc406Sopenharmony_ci  i = 0;
1855141cc406Sopenharmony_ci  default_source = s->dev->info.default_scan_mode;
1856141cc406Sopenharmony_ci
1857141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
1858141cc406Sopenharmony_ci  /* The JX330, but nut not the JX250 supports auto selection of ADF/FSU: */
1859141cc406Sopenharmony_ci  if (s->dev->info.adf_fsu_installed && (s->dev->sensedat.model == JX330))
1860141cc406Sopenharmony_ci    s->dev->info->scansources[i++] = use_auto;
1861141cc406Sopenharmony_ci#endif
1862141cc406Sopenharmony_ci  if (s->dev->info.adf_fsu_installed & HAVE_ADF)
1863141cc406Sopenharmony_ci    {
1864141cc406Sopenharmony_ci      if (default_source == -1)
1865141cc406Sopenharmony_ci        default_source = SCAN_WITH_ADF;
1866141cc406Sopenharmony_ci      if (default_source == SCAN_WITH_ADF)
1867141cc406Sopenharmony_ci        sourcename_index = i;
1868141cc406Sopenharmony_ci      s->dev->info.scansources[i++] = use_adf;
1869141cc406Sopenharmony_ci    }
1870141cc406Sopenharmony_ci  else
1871141cc406Sopenharmony_ci    {
1872141cc406Sopenharmony_ci      if (default_source == SCAN_WITH_ADF)
1873141cc406Sopenharmony_ci        default_source = SCAN_SIMPLE;
1874141cc406Sopenharmony_ci    }
1875141cc406Sopenharmony_ci  if (s->dev->info.adf_fsu_installed & HAVE_FSU)
1876141cc406Sopenharmony_ci    {
1877141cc406Sopenharmony_ci      if (default_source == -1)
1878141cc406Sopenharmony_ci        default_source = SCAN_WITH_FSU;
1879141cc406Sopenharmony_ci      if (default_source == SCAN_WITH_FSU)
1880141cc406Sopenharmony_ci        sourcename_index = i;
1881141cc406Sopenharmony_ci      s->dev->info.scansources[i++] = use_fsu;
1882141cc406Sopenharmony_ci    }
1883141cc406Sopenharmony_ci  else
1884141cc406Sopenharmony_ci    {
1885141cc406Sopenharmony_ci      if (default_source == SCAN_WITH_FSU)
1886141cc406Sopenharmony_ci        default_source = SCAN_SIMPLE;
1887141cc406Sopenharmony_ci    }
1888141cc406Sopenharmony_ci  if (default_source < 0)
1889141cc406Sopenharmony_ci    default_source = SCAN_SIMPLE;
1890141cc406Sopenharmony_ci  if (default_source == SCAN_SIMPLE)
1891141cc406Sopenharmony_ci    sourcename_index = i;
1892141cc406Sopenharmony_ci  s->dev->info.scansources[i++] = use_simple;
1893141cc406Sopenharmony_ci  s->dev->info.scansources[i] = 0;
1894141cc406Sopenharmony_ci
1895141cc406Sopenharmony_ci#if 0
1896141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].name = SANE_NAME_SCAN_SOURCE;
1897141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].title = SANE_TITLE_SCAN_SOURCE;
1898141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].desc = SANE_DESC_SCAN_SOURCE;
1899141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].type = SANE_TYPE_STRING;
1900141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].size = max_string_size (s->dev->info.scansources);
1901141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1902141cc406Sopenharmony_ci  s->opt[OPT_SCANSOURCE].constraint.string_list = (SANE_String_Const*)s->dev->info.scansources;
1903141cc406Sopenharmony_ci  s->val[OPT_SCANSOURCE].s = strdup (s->dev->info.scansources[0]);
1904141cc406Sopenharmony_ci#endif
1905141cc406Sopenharmony_ci
1906141cc406Sopenharmony_ci  init_string_option(s, SANE_NAME_SCAN_SOURCE, SANE_TITLE_SCAN_SOURCE,
1907141cc406Sopenharmony_ci    SANE_DESC_SCAN_SOURCE, (SANE_String_Const*)s->dev->info.scansources,
1908141cc406Sopenharmony_ci    OPT_SCANSOURCE, sourcename_index);
1909141cc406Sopenharmony_ci
1910141cc406Sopenharmony_ci  if (i < 2)
1911141cc406Sopenharmony_ci    s->opt[OPT_SCANSOURCE].cap |= SANE_CAP_INACTIVE;
1912141cc406Sopenharmony_ci
1913141cc406Sopenharmony_ci#if 0
1914141cc406Sopenharmony_ci  s->opt[OPT_PAPER].name = "Paper size";
1915141cc406Sopenharmony_ci  s->opt[OPT_PAPER].title = "Paper size";
1916141cc406Sopenharmony_ci  s->opt[OPT_PAPER].desc = "Paper size";
1917141cc406Sopenharmony_ci  s->opt[OPT_PAPER].type = SANE_TYPE_STRING;
1918141cc406Sopenharmony_ci  /* xxx the possible values for the paper size should be changeable,
1919141cc406Sopenharmony_ci     to reflect the different maximum scan sizes with/without ADF and FSU
1920141cc406Sopenharmony_ci  */
1921141cc406Sopenharmony_ci  if (s->dev->sensedat.model == JX610)
1922141cc406Sopenharmony_ci    {
1923141cc406Sopenharmony_ci      s->opt[OPT_PAPER].size = max_string_size (paper_list_jx610);
1924141cc406Sopenharmony_ci      s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1925141cc406Sopenharmony_ci      s->opt[OPT_PAPER].constraint.string_list = paper_list_jx610;
1926141cc406Sopenharmony_ci      s->val[OPT_PAPER].s = strdup (paper_list_jx610[1]);
1927141cc406Sopenharmony_ci    }
1928141cc406Sopenharmony_ci  else
1929141cc406Sopenharmony_ci    {
1930141cc406Sopenharmony_ci      s->opt[OPT_PAPER].size = max_string_size (paper_list_jx330);
1931141cc406Sopenharmony_ci      s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1932141cc406Sopenharmony_ci      s->opt[OPT_PAPER].constraint.string_list = paper_list_jx330;
1933141cc406Sopenharmony_ci      s->val[OPT_PAPER].s = strdup (paper_list_jx330[0]);
1934141cc406Sopenharmony_ci    }
1935141cc406Sopenharmony_ci#endif
1936141cc406Sopenharmony_ci
1937141cc406Sopenharmony_ci  if (s->dev->sensedat.model == JX610)
1938141cc406Sopenharmony_ci    init_string_option(s, "Paper size", "Paper size",
1939141cc406Sopenharmony_ci      "Paper size", paper_list_jx610, OPT_PAPER, 1);
1940141cc406Sopenharmony_ci  else
1941141cc406Sopenharmony_ci    init_string_option(s, "Paper size", "Paper size",
1942141cc406Sopenharmony_ci      "Paper size", paper_list_jx330, OPT_PAPER, 0);
1943141cc406Sopenharmony_ci
1944141cc406Sopenharmony_ci  /* gamma */
1945141cc406Sopenharmony_ci#if 0
1946141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].name = "Gamma";
1947141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].title = "Gamma";
1948141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].desc = "Gamma";
1949141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].type = SANE_TYPE_STRING;
1950141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].size = max_string_size (gamma_list);
1951141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1952141cc406Sopenharmony_ci  s->opt[OPT_GAMMA].constraint.string_list = gamma_list;
1953141cc406Sopenharmony_ci  s->val[OPT_GAMMA].s = strdup (gamma_list[1]);
1954141cc406Sopenharmony_ci#endif
1955141cc406Sopenharmony_ci
1956141cc406Sopenharmony_ci  init_string_option(s, "Gamma", "Gamma", "Gamma", gamma_list, OPT_GAMMA, 1);
1957141cc406Sopenharmony_ci
1958141cc406Sopenharmony_ci  /* scan speed */
1959141cc406Sopenharmony_ci  s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED;
1960141cc406Sopenharmony_ci  s->opt[OPT_SPEED].title = "Scan speed [fast]";
1961141cc406Sopenharmony_ci  s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED;
1962141cc406Sopenharmony_ci  s->opt[OPT_SPEED].type = SANE_TYPE_BOOL;
1963141cc406Sopenharmony_ci  s->val[OPT_SPEED].w = SANE_TRUE;
1964141cc406Sopenharmony_ci
1965141cc406Sopenharmony_ci  /* Resolution Group */
1966141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION_GROUP].title = "Resolution";
1967141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION_GROUP].desc = "";
1968141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION_GROUP].type = SANE_TYPE_GROUP;
1969141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION_GROUP].cap = 0;
1970141cc406Sopenharmony_ci  s->opt[OPT_RESOLUTION_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
1971141cc406Sopenharmony_ci
1972141cc406Sopenharmony_ci  /* select resolution */
1973141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST
1974141cc406Sopenharmony_ci  if (s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX330 ||
1975141cc406Sopenharmony_ci      s->dev->sensedat.model == JX350 || s->dev->sensedat.model == JX320)
1976141cc406Sopenharmony_ci    init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList",
1977141cc406Sopenharmony_ci      resolution_list_jx610, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX610);
1978141cc406Sopenharmony_ci  else
1979141cc406Sopenharmony_ci    init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList",
1980141cc406Sopenharmony_ci      resolution_list_jx250, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX250);
1981141cc406Sopenharmony_ci#endif
1982141cc406Sopenharmony_ci  /* x resolution */
1983141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
1984141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
1985141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
1986141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
1987141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
1988141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
1989141cc406Sopenharmony_ci  s->opt[OPT_X_RESOLUTION].constraint.range = &s->dev->info.xres_range;
1990141cc406Sopenharmony_ci  s->val[OPT_X_RESOLUTION].w = s->dev->info.xres_default;
1991141cc406Sopenharmony_ci
1992141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
1993141cc406Sopenharmony_ci  /* y resolution */
1994141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION;
1995141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION;
1996141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
1997141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
1998141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
1999141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
2000141cc406Sopenharmony_ci  s->opt[OPT_Y_RESOLUTION].constraint.range = &s->dev->info.yres_range;
2001141cc406Sopenharmony_ci  s->val[OPT_Y_RESOLUTION].w = s->dev->info.yres_default;
2002141cc406Sopenharmony_ci#endif
2003141cc406Sopenharmony_ci
2004141cc406Sopenharmony_ci  /* "Geometry" group: */
2005141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
2006141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].desc = "";
2007141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2008141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2009141cc406Sopenharmony_ci  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2010141cc406Sopenharmony_ci
2011141cc406Sopenharmony_ci  /* top-left x */
2012141cc406Sopenharmony_ci  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2013141cc406Sopenharmony_ci  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2014141cc406Sopenharmony_ci  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2015141cc406Sopenharmony_ci  s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2016141cc406Sopenharmony_ci  s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2017141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2018141cc406Sopenharmony_ci  s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[default_source];
2019141cc406Sopenharmony_ci  s->val[OPT_TL_X].w = s->dev->info.tl_x_ranges[default_source].min;
2020141cc406Sopenharmony_ci
2021141cc406Sopenharmony_ci  /* top-left y */
2022141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2023141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2024141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2025141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2026141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2027141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2028141cc406Sopenharmony_ci  s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[default_source];
2029141cc406Sopenharmony_ci  s->val[OPT_TL_Y].w = s->dev->info.tl_y_ranges[default_source].min;
2030141cc406Sopenharmony_ci
2031141cc406Sopenharmony_ci  /* bottom-right x */
2032141cc406Sopenharmony_ci  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2033141cc406Sopenharmony_ci  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2034141cc406Sopenharmony_ci  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2035141cc406Sopenharmony_ci  s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2036141cc406Sopenharmony_ci  s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2037141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2038141cc406Sopenharmony_ci  s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[default_source];
2039141cc406Sopenharmony_ci  scalar = s->dev->info.x_default;
2040141cc406Sopenharmony_ci  clip_value (&s->opt[OPT_BR_X], &scalar);
2041141cc406Sopenharmony_ci  s->val[OPT_BR_X].w = scalar;
2042141cc406Sopenharmony_ci
2043141cc406Sopenharmony_ci  /* bottom-right y */
2044141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2045141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2046141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2047141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2048141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2049141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2050141cc406Sopenharmony_ci  s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[default_source];
2051141cc406Sopenharmony_ci  /* The FSU for JX250 allows a maximum scan length of 11.5 inch,
2052141cc406Sopenharmony_ci     which is less than the default value of 297 mm
2053141cc406Sopenharmony_ci  */
2054141cc406Sopenharmony_ci  scalar = s->dev->info.y_default;
2055141cc406Sopenharmony_ci  clip_value (&s->opt[OPT_BR_X], &scalar);
2056141cc406Sopenharmony_ci  s->val[OPT_BR_Y].w = scalar;
2057141cc406Sopenharmony_ci
2058141cc406Sopenharmony_ci  /* "Enhancement" group: */
2059141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
2060141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
2061141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
2062141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
2063141cc406Sopenharmony_ci  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2064141cc406Sopenharmony_ci
2065141cc406Sopenharmony_ci  /* edge emphasis */
2066141cc406Sopenharmony_ci#if 0
2067141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].name = "Edge emphasis";
2068141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].title = "Edge emphasis";
2069141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].desc = "Edge emphasis";
2070141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].type = SANE_TYPE_STRING;
2071141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].size = max_string_size (edge_emphasis_list);
2072141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2073141cc406Sopenharmony_ci  s->opt[OPT_EDGE_EMPHASIS].constraint.string_list = edge_emphasis_list;
2074141cc406Sopenharmony_ci  s->val[OPT_EDGE_EMPHASIS].s = strdup (edge_emphasis_list[0]);
2075141cc406Sopenharmony_ci#endif
2076141cc406Sopenharmony_ci  init_string_option(s, "Edge emphasis", "Edge emphasis",
2077141cc406Sopenharmony_ci    "Edge emphasis", edge_emphasis_list,
2078141cc406Sopenharmony_ci    OPT_EDGE_EMPHASIS, 0);
2079141cc406Sopenharmony_ci
2080141cc406Sopenharmony_ci  if (   s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350
2081141cc406Sopenharmony_ci      || s->dev->sensedat.model == JX320)
2082141cc406Sopenharmony_ci    s->opt[OPT_EDGE_EMPHASIS].cap |= SANE_CAP_INACTIVE;
2083141cc406Sopenharmony_ci
2084141cc406Sopenharmony_ci  /* threshold */
2085141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
2086141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
2087141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
2088141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
2089141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
2090141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
2091141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].constraint.range = &s->dev->info.threshold_range;
2092141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD].w = 128;
2093141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2094141cc406Sopenharmony_ci
2095141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2096141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].name = SANE_NAME_THRESHOLD "-red";
2097141cc406Sopenharmony_ci  /* xxx the titles and descriptions are confusing:
2098141cc406Sopenharmony_ci     "set white point (red)"
2099141cc406Sopenharmony_ci     Any idea? maybe "threshold to get the red component on"
2100141cc406Sopenharmony_ci  */
2101141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].title = SANE_TITLE_THRESHOLD " (red)";
2102141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].desc = SANE_DESC_THRESHOLD " (red)";
2103141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].type = SANE_TYPE_INT;
2104141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].unit = SANE_UNIT_NONE;
2105141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].constraint_type = SANE_CONSTRAINT_RANGE;
2106141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].constraint.range = &s->dev->info.threshold_range;
2107141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD_R].w = 128;
2108141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE;
2109141cc406Sopenharmony_ci
2110141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].name = SANE_NAME_THRESHOLD "-green";
2111141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].title = SANE_TITLE_THRESHOLD " (green)";
2112141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].desc = SANE_DESC_THRESHOLD " (green)";
2113141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].type = SANE_TYPE_INT;
2114141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].unit = SANE_UNIT_NONE;
2115141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].constraint_type = SANE_CONSTRAINT_RANGE;
2116141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].constraint.range = &s->dev->info.threshold_range;
2117141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD_G].w = 128;
2118141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE;
2119141cc406Sopenharmony_ci
2120141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].name = SANE_NAME_THRESHOLD "-blue";
2121141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].title = SANE_TITLE_THRESHOLD " (blue)";
2122141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].desc = SANE_DESC_THRESHOLD " (blue)";
2123141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].type = SANE_TYPE_INT;
2124141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].unit = SANE_UNIT_NONE;
2125141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].constraint_type = SANE_CONSTRAINT_RANGE;
2126141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].constraint.range = &s->dev->info.threshold_range;
2127141cc406Sopenharmony_ci  s->val[OPT_THRESHOLD_B].w = 128;
2128141cc406Sopenharmony_ci  s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE;
2129141cc406Sopenharmony_ci
2130141cc406Sopenharmony_ci#endif
2131141cc406Sopenharmony_ci
2132141cc406Sopenharmony_ci  /* light color (for gray scale and line art scans) */
2133141cc406Sopenharmony_ci#if 0
2134141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].name = "LightColor";
2135141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].title = "Light Color";
2136141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].desc = "Light Color";
2137141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].type = SANE_TYPE_STRING;
2138141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].size = max_string_size (light_color_list);
2139141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2140141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].constraint.string_list = light_color_list;
2141141cc406Sopenharmony_ci  s->val[OPT_LIGHTCOLOR].s = strdup (light_color_list[3]);
2142141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE;
2143141cc406Sopenharmony_ci#endif
2144141cc406Sopenharmony_ci  init_string_option(s, "LightColor", "LightColor", "LightColor",
2145141cc406Sopenharmony_ci    light_color_list, OPT_LIGHTCOLOR, 3);
2146141cc406Sopenharmony_ci  s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE;
2147141cc406Sopenharmony_ci
2148141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].name  = SANE_NAME_PREVIEW;
2149141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2150141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].desc  = SANE_DESC_PREVIEW;
2151141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].type  = SANE_TYPE_BOOL;
2152141cc406Sopenharmony_ci  s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
2153141cc406Sopenharmony_ci  s->val[OPT_PREVIEW].w     = SANE_FALSE;
2154141cc406Sopenharmony_ci
2155141cc406Sopenharmony_ci
2156141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2157141cc406Sopenharmony_ci  /* custom-gamma table */
2158141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
2159141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
2160141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
2161141cc406Sopenharmony_ci  s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
2162141cc406Sopenharmony_ci  s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE;
2163141cc406Sopenharmony_ci
2164141cc406Sopenharmony_ci  /* grayscale gamma vector */
2165141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
2166141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
2167141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
2168141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
2169141cc406Sopenharmony_ci#if 0
2170141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
2171141cc406Sopenharmony_ci#endif
2172141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
2173141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word);
2174141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
2175141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range;
2176141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0];
2177141cc406Sopenharmony_ci
2178141cc406Sopenharmony_ci  /* red gamma vector */
2179141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
2180141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
2181141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
2182141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
2183141cc406Sopenharmony_ci#if 0
2184141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
2185141cc406Sopenharmony_ci#endif
2186141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
2187141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word);
2188141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
2189141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
2190141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0];
2191141cc406Sopenharmony_ci
2192141cc406Sopenharmony_ci  /* green gamma vector */
2193141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
2194141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
2195141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
2196141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
2197141cc406Sopenharmony_ci#if 0
2198141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
2199141cc406Sopenharmony_ci#endif
2200141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
2201141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word);
2202141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
2203141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
2204141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0];
2205141cc406Sopenharmony_ci
2206141cc406Sopenharmony_ci  /* blue gamma vector */
2207141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
2208141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
2209141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
2210141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
2211141cc406Sopenharmony_ci#if 0
2212141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
2213141cc406Sopenharmony_ci#endif
2214141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
2215141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word);
2216141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
2217141cc406Sopenharmony_ci  s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
2218141cc406Sopenharmony_ci  s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0];
2219141cc406Sopenharmony_ci  set_gamma_caps(s);
2220141cc406Sopenharmony_ci#endif
2221141cc406Sopenharmony_ci
2222141cc406Sopenharmony_ci  DBG (10, ">>\n");
2223141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2224141cc406Sopenharmony_ci}
2225141cc406Sopenharmony_ci
2226141cc406Sopenharmony_cistatic SANE_Status
2227141cc406Sopenharmony_cido_cancel (SHARP_Scanner * s)
2228141cc406Sopenharmony_ci{
2229141cc406Sopenharmony_ci  static u_char cmd[] = {READ, 0, 0, 0, 0, 2, 0, 0, 0, 0};
2230141cc406Sopenharmony_ci
2231141cc406Sopenharmony_ci  DBG (10, "<< do_cancel ");
2232141cc406Sopenharmony_ci
2233141cc406Sopenharmony_ci#ifdef USE_FORK
2234141cc406Sopenharmony_ci  if (s->reader_pid > 0)
2235141cc406Sopenharmony_ci    {
2236141cc406Sopenharmony_ci      int exit_status;
2237141cc406Sopenharmony_ci      int count = 0;
2238141cc406Sopenharmony_ci      /* ensure child knows it's time to stop: */
2239141cc406Sopenharmony_ci
2240141cc406Sopenharmony_ci      DBG(11, "stopping reader process\n");
2241141cc406Sopenharmony_ci      s->rdr_ctl->cancel = 1;
2242141cc406Sopenharmony_ci      while(reader_running(s) && count < 100)
2243141cc406Sopenharmony_ci        {
2244141cc406Sopenharmony_ci          usleep(100000);
2245141cc406Sopenharmony_ci          count++;
2246141cc406Sopenharmony_ci        };
2247141cc406Sopenharmony_ci      if (reader_running(s))
2248141cc406Sopenharmony_ci        {
2249141cc406Sopenharmony_ci          /* be brutal...
2250141cc406Sopenharmony_ci             !! The waiting time of 10 seconds might be far too short
2251141cc406Sopenharmony_ci             !! if the resolution limit of the JX 250 is increased to
2252141cc406Sopenharmony_ci             !! to more than 400 dpi: for these (interpolated) resolutions,
2253141cc406Sopenharmony_ci             !! the JX 250 is awfully slow.
2254141cc406Sopenharmony_ci          */
2255141cc406Sopenharmony_ci          kill(s->reader_pid, SIGKILL);
2256141cc406Sopenharmony_ci        }
2257141cc406Sopenharmony_ci      wait(&exit_status);
2258141cc406Sopenharmony_ci      DBG(11, "reader process stopped\n");
2259141cc406Sopenharmony_ci
2260141cc406Sopenharmony_ci      s->reader_pid = 0;
2261141cc406Sopenharmony_ci    }
2262141cc406Sopenharmony_ci
2263141cc406Sopenharmony_ci#endif
2264141cc406Sopenharmony_ci  if (s->scanning == SANE_TRUE)
2265141cc406Sopenharmony_ci    {
2266141cc406Sopenharmony_ci      wait_ready(s->fd);
2267141cc406Sopenharmony_ci      sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
2268141cc406Sopenharmony_ci      /* if (s->adf_scan) */
2269141cc406Sopenharmony_ci      if (   s->dev->sensedat.model != JX610
2270141cc406Sopenharmony_ci          && s->dev->sensedat.model != JX320)
2271141cc406Sopenharmony_ci        object_position(s->fd, UNLOAD_PAPER);
2272141cc406Sopenharmony_ci    }
2273141cc406Sopenharmony_ci
2274141cc406Sopenharmony_ci  s->scanning = SANE_FALSE;
2275141cc406Sopenharmony_ci
2276141cc406Sopenharmony_ci  if (s->fd >= 0)
2277141cc406Sopenharmony_ci    {
2278141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
2279141cc406Sopenharmony_ci      s->fd = -1;
2280141cc406Sopenharmony_ci    }
2281141cc406Sopenharmony_ci#ifdef USE_FORK
2282141cc406Sopenharmony_ci  {
2283141cc406Sopenharmony_ci    struct shmid_ds ds;
2284141cc406Sopenharmony_ci    if (s->shmid != -1)
2285141cc406Sopenharmony_ci      shmctl(s->shmid, IPC_RMID, &ds);
2286141cc406Sopenharmony_ci    s->shmid = -1;
2287141cc406Sopenharmony_ci  }
2288141cc406Sopenharmony_ci#endif
2289141cc406Sopenharmony_ci  if (s->buffer)
2290141cc406Sopenharmony_ci    free(s->buffer);
2291141cc406Sopenharmony_ci  s->buffer = 0;
2292141cc406Sopenharmony_ci
2293141cc406Sopenharmony_ci  DBG (10, ">>\n");
2294141cc406Sopenharmony_ci  return (SANE_STATUS_CANCELLED);
2295141cc406Sopenharmony_ci}
2296141cc406Sopenharmony_ci
2297141cc406Sopenharmony_cistatic SHARP_New_Device *new_devs = 0;
2298141cc406Sopenharmony_cistatic SHARP_New_Device *new_dev_pool = 0;
2299141cc406Sopenharmony_ci
2300141cc406Sopenharmony_cistatic SANE_Status
2301141cc406Sopenharmony_ciattach_and_list(const char *devnam)
2302141cc406Sopenharmony_ci{
2303141cc406Sopenharmony_ci  SANE_Status res;
2304141cc406Sopenharmony_ci  SHARP_Device *devp;
2305141cc406Sopenharmony_ci  SHARP_New_Device *np;
2306141cc406Sopenharmony_ci
2307141cc406Sopenharmony_ci  res = attach(devnam, &devp);
2308141cc406Sopenharmony_ci  if (res == SANE_STATUS_GOOD)
2309141cc406Sopenharmony_ci    {
2310141cc406Sopenharmony_ci      if (new_dev_pool)
2311141cc406Sopenharmony_ci        {
2312141cc406Sopenharmony_ci          np = new_dev_pool;
2313141cc406Sopenharmony_ci          new_dev_pool = np->next;
2314141cc406Sopenharmony_ci        }
2315141cc406Sopenharmony_ci      else
2316141cc406Sopenharmony_ci        {
2317141cc406Sopenharmony_ci          np = malloc(sizeof(SHARP_New_Device));
2318141cc406Sopenharmony_ci          if (np == 0)
2319141cc406Sopenharmony_ci            return SANE_STATUS_NO_MEM;
2320141cc406Sopenharmony_ci        }
2321141cc406Sopenharmony_ci      np->next =new_devs;
2322141cc406Sopenharmony_ci      np->dev = devp;
2323141cc406Sopenharmony_ci      new_devs = np;
2324141cc406Sopenharmony_ci    }
2325141cc406Sopenharmony_ci  return res;
2326141cc406Sopenharmony_ci}
2327141cc406Sopenharmony_ci
2328141cc406Sopenharmony_cistatic int buffers[2] = {DEFAULT_BUFFERS, DEFAULT_BUFFERS};
2329141cc406Sopenharmony_cistatic int bufsize[2] = {DEFAULT_BUFSIZE, DEFAULT_BUFSIZE};
2330141cc406Sopenharmony_cistatic int queued_reads[2] = {DEFAULT_QUEUED_READS, DEFAULT_QUEUED_READS};
2331141cc406Sopenharmony_cistatic int stop_on_fsu_error[2] = {COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR,
2332141cc406Sopenharmony_ci                                   COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR};
2333141cc406Sopenharmony_cistatic int default_scan_mode[2] = {-1, -1};
2334141cc406Sopenharmony_ci
2335141cc406Sopenharmony_ciSANE_Status
2336141cc406Sopenharmony_cisane_init (SANE_Int * version_code,
2337141cc406Sopenharmony_ci	   SANE_Auth_Callback __sane_unused__ authorize)
2338141cc406Sopenharmony_ci{
2339141cc406Sopenharmony_ci  char devnam[PATH_MAX] = "/dev/scanner";
2340141cc406Sopenharmony_ci  char line[PATH_MAX];
2341141cc406Sopenharmony_ci  const char *lp;
2342141cc406Sopenharmony_ci  char *word;
2343141cc406Sopenharmony_ci  char *end;
2344141cc406Sopenharmony_ci  FILE *fp;
2345141cc406Sopenharmony_ci  int opt_index = 0;
2346141cc406Sopenharmony_ci  int linecount = 0;
2347141cc406Sopenharmony_ci#if 1
2348141cc406Sopenharmony_ci  SHARP_Device sd;
2349141cc406Sopenharmony_ci  SHARP_Device *dp = &sd;
2350141cc406Sopenharmony_ci#else
2351141cc406Sopenharmony_ci  SHARP_Device *dp;
2352141cc406Sopenharmony_ci#endif
2353141cc406Sopenharmony_ci  SHARP_New_Device *np;
2354141cc406Sopenharmony_ci  int i;
2355141cc406Sopenharmony_ci
2356141cc406Sopenharmony_ci  DBG_INIT ();
2357141cc406Sopenharmony_ci  DBG (10, "<< sane_init ");
2358141cc406Sopenharmony_ci
2359141cc406Sopenharmony_ci#if defined PACKAGE && defined VERSION
2360141cc406Sopenharmony_ci  DBG (2, "sane_init: " PACKAGE " " VERSION "\n");
2361141cc406Sopenharmony_ci#endif
2362141cc406Sopenharmony_ci
2363141cc406Sopenharmony_ci  if (version_code)
2364141cc406Sopenharmony_ci    *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
2365141cc406Sopenharmony_ci
2366141cc406Sopenharmony_ci  fp = sanei_config_open (SHARP_CONFIG_FILE);
2367141cc406Sopenharmony_ci  if (!fp)
2368141cc406Sopenharmony_ci    {
2369141cc406Sopenharmony_ci      /* use "/dev/scanner" as the default device name if no
2370141cc406Sopenharmony_ci         config file is available
2371141cc406Sopenharmony_ci      */
2372141cc406Sopenharmony_ci      attach (devnam, &dp);
2373141cc406Sopenharmony_ci      /* make sure that there are at least two buffers */
2374141cc406Sopenharmony_ci      if (DEFAULT_BUFFERS < 2)
2375141cc406Sopenharmony_ci        dp->info.buffers = DEFAULT_BUFFERS;
2376141cc406Sopenharmony_ci      else
2377141cc406Sopenharmony_ci        dp->info.buffers = 2;
2378141cc406Sopenharmony_ci      dp->info.wanted_bufsize = DEFAULT_BUFSIZE;
2379141cc406Sopenharmony_ci      dp->info.queued_reads = DEFAULT_QUEUED_READS;
2380141cc406Sopenharmony_ci      dp->info.complain_on_errors = COMPLAIN_ON_ADF_ERROR | COMPLAIN_ON_FSU_ERROR;
2381141cc406Sopenharmony_ci      dp->info.default_scan_mode = -1;
2382141cc406Sopenharmony_ci      return SANE_STATUS_GOOD;
2383141cc406Sopenharmony_ci    }
2384141cc406Sopenharmony_ci
2385141cc406Sopenharmony_ci  while (fgets(line, PATH_MAX, fp))
2386141cc406Sopenharmony_ci    {
2387141cc406Sopenharmony_ci      linecount++;
2388141cc406Sopenharmony_ci      word = 0;
2389141cc406Sopenharmony_ci      lp = sanei_config_get_string(line, &word);
2390141cc406Sopenharmony_ci      if (word)
2391141cc406Sopenharmony_ci        {
2392141cc406Sopenharmony_ci          if (word[0] != '#')
2393141cc406Sopenharmony_ci            {
2394141cc406Sopenharmony_ci              if (strcmp(word, "option") == 0)
2395141cc406Sopenharmony_ci                {
2396141cc406Sopenharmony_ci                  free(word);
2397141cc406Sopenharmony_ci                  word = 0;
2398141cc406Sopenharmony_ci                  lp = sanei_config_get_string(lp, &word);
2399141cc406Sopenharmony_ci                  if (strcmp(word, "buffers") == 0)
2400141cc406Sopenharmony_ci                    {
2401141cc406Sopenharmony_ci                      free(word);
2402141cc406Sopenharmony_ci                      word = 0;
2403141cc406Sopenharmony_ci                      sanei_config_get_string(lp, &word);
2404141cc406Sopenharmony_ci                      i = strtol(word, &end, 0);
2405141cc406Sopenharmony_ci                      if (end == word)
2406141cc406Sopenharmony_ci                        {
2407141cc406Sopenharmony_ci                          DBG(1, "error in config file, line %i: number expected:\n",
2408141cc406Sopenharmony_ci                              linecount);
2409141cc406Sopenharmony_ci                          DBG(1, "%s\n", line);
2410141cc406Sopenharmony_ci                        }
2411141cc406Sopenharmony_ci                      else
2412141cc406Sopenharmony_ci                        if (i > 2)
2413141cc406Sopenharmony_ci                          buffers[opt_index] = i;
2414141cc406Sopenharmony_ci                        else
2415141cc406Sopenharmony_ci                          buffers[opt_index] = 2;
2416141cc406Sopenharmony_ci                    }
2417141cc406Sopenharmony_ci                  else if (strcmp(word, "buffersize") == 0)
2418141cc406Sopenharmony_ci                    {
2419141cc406Sopenharmony_ci                      free(word);
2420141cc406Sopenharmony_ci                      word = 0;
2421141cc406Sopenharmony_ci                      sanei_config_get_string(lp, &word);
2422141cc406Sopenharmony_ci                      i = strtol(word, &end, 0);
2423141cc406Sopenharmony_ci                      if (word == end)
2424141cc406Sopenharmony_ci                        {
2425141cc406Sopenharmony_ci                          DBG(1, "error in config file, line %i: number expected:\n",
2426141cc406Sopenharmony_ci                              linecount);
2427141cc406Sopenharmony_ci                          DBG(1, "%s\n", line);
2428141cc406Sopenharmony_ci                        }
2429141cc406Sopenharmony_ci                      else
2430141cc406Sopenharmony_ci                        bufsize[opt_index] = i;
2431141cc406Sopenharmony_ci                    }
2432141cc406Sopenharmony_ci                  else if (strcmp(word, "readqueue") == 0)
2433141cc406Sopenharmony_ci                    {
2434141cc406Sopenharmony_ci                      free(word);
2435141cc406Sopenharmony_ci                      word = 0;
2436141cc406Sopenharmony_ci                      sanei_config_get_string(lp, &word);
2437141cc406Sopenharmony_ci                      i = strtol(word, &end, 0);
2438141cc406Sopenharmony_ci                      if (word == end)
2439141cc406Sopenharmony_ci                        {
2440141cc406Sopenharmony_ci                          DBG(1, "error in config file, line %i: number expected:\n",
2441141cc406Sopenharmony_ci                              linecount);
2442141cc406Sopenharmony_ci                          DBG(1, "%s\n", line);
2443141cc406Sopenharmony_ci                        }
2444141cc406Sopenharmony_ci                      else
2445141cc406Sopenharmony_ci                        queued_reads[opt_index] = i;
2446141cc406Sopenharmony_ci                    }
2447141cc406Sopenharmony_ci                  else if (strcmp(word, "stop_on_fsu_error") == 0)
2448141cc406Sopenharmony_ci                    {
2449141cc406Sopenharmony_ci                      free(word);
2450141cc406Sopenharmony_ci                      word = 0;
2451141cc406Sopenharmony_ci                      sanei_config_get_string(lp, &word);
2452141cc406Sopenharmony_ci                      i = strtol(word, &end, 0);
2453141cc406Sopenharmony_ci                      if (word == end)
2454141cc406Sopenharmony_ci                        {
2455141cc406Sopenharmony_ci                          DBG(1, "error in config file, line %i: number expected:\n",
2456141cc406Sopenharmony_ci                              linecount);
2457141cc406Sopenharmony_ci                          DBG(1, "%s\n", line);
2458141cc406Sopenharmony_ci                        }
2459141cc406Sopenharmony_ci                      else
2460141cc406Sopenharmony_ci                        stop_on_fsu_error[opt_index]
2461141cc406Sopenharmony_ci                          = i ? COMPLAIN_ON_FSU_ERROR : 0;
2462141cc406Sopenharmony_ci                    }
2463141cc406Sopenharmony_ci                  else if (strcmp(word, "default_scan_source") == 0)
2464141cc406Sopenharmony_ci                    {
2465141cc406Sopenharmony_ci                      free(word);
2466141cc406Sopenharmony_ci                      word = 0;
2467141cc406Sopenharmony_ci                      sanei_config_get_string(lp, &word);
2468141cc406Sopenharmony_ci                      if (strcmp(word, "auto") == 0)
2469141cc406Sopenharmony_ci                        default_scan_mode[opt_index] = -1;
2470141cc406Sopenharmony_ci                      else if (strcmp(word, "fsu") == 0)
2471141cc406Sopenharmony_ci                        default_scan_mode[opt_index] = SCAN_WITH_FSU;
2472141cc406Sopenharmony_ci                      else if (strcmp(word, "adf") == 0)
2473141cc406Sopenharmony_ci                        default_scan_mode[opt_index] = SCAN_WITH_ADF;
2474141cc406Sopenharmony_ci                      else if (strcmp(word, "flatbed") == 0)
2475141cc406Sopenharmony_ci                        default_scan_mode[opt_index] = SCAN_SIMPLE;
2476141cc406Sopenharmony_ci                      else
2477141cc406Sopenharmony_ci                        {
2478141cc406Sopenharmony_ci                          DBG(1, "error in config file, line %i: number expected:\n",
2479141cc406Sopenharmony_ci                              linecount);
2480141cc406Sopenharmony_ci                          DBG(1, "%s\n", line);
2481141cc406Sopenharmony_ci                        }
2482141cc406Sopenharmony_ci                    }
2483141cc406Sopenharmony_ci                  else
2484141cc406Sopenharmony_ci                    {
2485141cc406Sopenharmony_ci                      DBG(1, "error in config file, line %i: unknown option\n",
2486141cc406Sopenharmony_ci                          linecount);
2487141cc406Sopenharmony_ci                      DBG(1, "%s\n", line);
2488141cc406Sopenharmony_ci                    }
2489141cc406Sopenharmony_ci                }
2490141cc406Sopenharmony_ci              else
2491141cc406Sopenharmony_ci                {
2492141cc406Sopenharmony_ci                  while (new_devs)
2493141cc406Sopenharmony_ci                    {
2494141cc406Sopenharmony_ci                      if (buffers[1] >= 2)
2495141cc406Sopenharmony_ci                        new_devs->dev->info.buffers = buffers[1];
2496141cc406Sopenharmony_ci                      else
2497141cc406Sopenharmony_ci                        new_devs->dev->info.buffers = 2;
2498141cc406Sopenharmony_ci                      if (bufsize[1] > 0)
2499141cc406Sopenharmony_ci                        new_devs->dev->info.wanted_bufsize = bufsize[1];
2500141cc406Sopenharmony_ci                      else
2501141cc406Sopenharmony_ci                        new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE;
2502141cc406Sopenharmony_ci                      if (queued_reads[1] >= 0)
2503141cc406Sopenharmony_ci                        new_devs->dev->info.queued_reads = queued_reads[1];
2504141cc406Sopenharmony_ci                      else
2505141cc406Sopenharmony_ci                        new_devs->dev->info.queued_reads = 0;
2506141cc406Sopenharmony_ci                      new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1];
2507141cc406Sopenharmony_ci                      new_devs->dev->info.default_scan_mode = default_scan_mode[1];
2508141cc406Sopenharmony_ci                      np = new_devs->next;
2509141cc406Sopenharmony_ci                      new_devs->next = new_dev_pool;
2510141cc406Sopenharmony_ci                      new_dev_pool = new_devs;
2511141cc406Sopenharmony_ci                      new_devs = np;
2512141cc406Sopenharmony_ci                    }
2513141cc406Sopenharmony_ci                  if (line[strlen(line)-1] == '\n')
2514141cc406Sopenharmony_ci                    line[strlen(line)-1] = 0;
2515141cc406Sopenharmony_ci                  sanei_config_attach_matching_devices(line, &attach_and_list);
2516141cc406Sopenharmony_ci                  buffers[1] = buffers[0];
2517141cc406Sopenharmony_ci                  bufsize[1] = bufsize[0];
2518141cc406Sopenharmony_ci                  queued_reads[1] = queued_reads[0];
2519141cc406Sopenharmony_ci                  stop_on_fsu_error[1] = stop_on_fsu_error[0];
2520141cc406Sopenharmony_ci                  default_scan_mode[1] = default_scan_mode[0];
2521141cc406Sopenharmony_ci                  opt_index = 1;
2522141cc406Sopenharmony_ci                }
2523141cc406Sopenharmony_ci            }
2524141cc406Sopenharmony_ci          if (word) free(word);
2525141cc406Sopenharmony_ci        }
2526141cc406Sopenharmony_ci    }
2527141cc406Sopenharmony_ci
2528141cc406Sopenharmony_ci  while (new_devs)
2529141cc406Sopenharmony_ci    {
2530141cc406Sopenharmony_ci      if (buffers[1] >= 2)
2531141cc406Sopenharmony_ci        new_devs->dev->info.buffers = buffers[1];
2532141cc406Sopenharmony_ci      else
2533141cc406Sopenharmony_ci        new_devs->dev->info.buffers = 2;
2534141cc406Sopenharmony_ci      if (bufsize[1] > 0)
2535141cc406Sopenharmony_ci        new_devs->dev->info.wanted_bufsize = bufsize[1];
2536141cc406Sopenharmony_ci      else
2537141cc406Sopenharmony_ci        new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE;
2538141cc406Sopenharmony_ci      if (queued_reads[1] >= 0)
2539141cc406Sopenharmony_ci        new_devs->dev->info.queued_reads = queued_reads[1];
2540141cc406Sopenharmony_ci      else
2541141cc406Sopenharmony_ci        new_devs->dev->info.queued_reads = 0;
2542141cc406Sopenharmony_ci      new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1];
2543141cc406Sopenharmony_ci      new_devs->dev->info.default_scan_mode = default_scan_mode[1];
2544141cc406Sopenharmony_ci      if (line[strlen(line)-1] == '\n')
2545141cc406Sopenharmony_ci        line[strlen(line)-1] = 0;
2546141cc406Sopenharmony_ci      np = new_devs->next;
2547141cc406Sopenharmony_ci      free(new_devs);
2548141cc406Sopenharmony_ci      new_devs = np;
2549141cc406Sopenharmony_ci    }
2550141cc406Sopenharmony_ci  while (new_dev_pool)
2551141cc406Sopenharmony_ci    {
2552141cc406Sopenharmony_ci      np = new_dev_pool->next;
2553141cc406Sopenharmony_ci      free(new_dev_pool);
2554141cc406Sopenharmony_ci      new_dev_pool = np;
2555141cc406Sopenharmony_ci    }
2556141cc406Sopenharmony_ci  fclose(fp);
2557141cc406Sopenharmony_ci  DBG (10, "sane_init >>\n");
2558141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
2559141cc406Sopenharmony_ci}
2560141cc406Sopenharmony_ci
2561141cc406Sopenharmony_cistatic const SANE_Device **devlist = 0;
2562141cc406Sopenharmony_civoid
2563141cc406Sopenharmony_cisane_exit (void)
2564141cc406Sopenharmony_ci{
2565141cc406Sopenharmony_ci  SHARP_Device *dev, *next;
2566141cc406Sopenharmony_ci  DBG (10, "<< sane_exit ");
2567141cc406Sopenharmony_ci
2568141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = next)
2569141cc406Sopenharmony_ci    {
2570141cc406Sopenharmony_ci      next = dev->next;
2571141cc406Sopenharmony_ci      free ((void *) dev->sane.name);
2572141cc406Sopenharmony_ci      free ((void *) dev->sane.model);
2573141cc406Sopenharmony_ci      free (dev);
2574141cc406Sopenharmony_ci    }
2575141cc406Sopenharmony_ci
2576141cc406Sopenharmony_ci  if (devlist)
2577141cc406Sopenharmony_ci    free(devlist);
2578141cc406Sopenharmony_ci  devlist = 0;
2579141cc406Sopenharmony_ci  first_dev = 0;
2580141cc406Sopenharmony_ci
2581141cc406Sopenharmony_ci  DBG (10, ">>\n");
2582141cc406Sopenharmony_ci}
2583141cc406Sopenharmony_ci
2584141cc406Sopenharmony_ciSANE_Status
2585141cc406Sopenharmony_cisane_get_devices (const SANE_Device *** device_list,
2586141cc406Sopenharmony_ci		  SANE_Bool __sane_unused__ local_only)
2587141cc406Sopenharmony_ci{
2588141cc406Sopenharmony_ci  SHARP_Device *dev;
2589141cc406Sopenharmony_ci  int i;
2590141cc406Sopenharmony_ci  DBG (10, "<< sane_get_devices ");
2591141cc406Sopenharmony_ci
2592141cc406Sopenharmony_ci  if (devlist)
2593141cc406Sopenharmony_ci    free (devlist);
2594141cc406Sopenharmony_ci  devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
2595141cc406Sopenharmony_ci  if (!devlist)
2596141cc406Sopenharmony_ci    return (SANE_STATUS_NO_MEM);
2597141cc406Sopenharmony_ci
2598141cc406Sopenharmony_ci  i = 0;
2599141cc406Sopenharmony_ci  for (dev = first_dev; dev; dev = dev->next)
2600141cc406Sopenharmony_ci    devlist[i++] = &dev->sane;
2601141cc406Sopenharmony_ci  devlist[i++] = 0;
2602141cc406Sopenharmony_ci
2603141cc406Sopenharmony_ci  *device_list = devlist;
2604141cc406Sopenharmony_ci
2605141cc406Sopenharmony_ci  DBG (10, ">>\n");
2606141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2607141cc406Sopenharmony_ci}
2608141cc406Sopenharmony_ci
2609141cc406Sopenharmony_ciSANE_Status
2610141cc406Sopenharmony_cisane_open (SANE_String_Const devnam, SANE_Handle * handle)
2611141cc406Sopenharmony_ci{
2612141cc406Sopenharmony_ci  SANE_Status status;
2613141cc406Sopenharmony_ci  SHARP_Device *dev;
2614141cc406Sopenharmony_ci  SHARP_Scanner *s;
2615141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2616141cc406Sopenharmony_ci  int i, j;
2617141cc406Sopenharmony_ci#endif
2618141cc406Sopenharmony_ci
2619141cc406Sopenharmony_ci  DBG (10, "<< sane_open ");
2620141cc406Sopenharmony_ci
2621141cc406Sopenharmony_ci  if (devnam[0])
2622141cc406Sopenharmony_ci    {
2623141cc406Sopenharmony_ci      for (dev = first_dev; dev; dev = dev->next)
2624141cc406Sopenharmony_ci	{
2625141cc406Sopenharmony_ci	  if (strcmp (dev->sane.name, devnam) == 0)
2626141cc406Sopenharmony_ci	    break;
2627141cc406Sopenharmony_ci	}
2628141cc406Sopenharmony_ci
2629141cc406Sopenharmony_ci      if (!dev)
2630141cc406Sopenharmony_ci	{
2631141cc406Sopenharmony_ci	  status = attach (devnam, &dev);
2632141cc406Sopenharmony_ci	  if (status != SANE_STATUS_GOOD)
2633141cc406Sopenharmony_ci	    return (status);
2634141cc406Sopenharmony_ci	  dev->info.buffers = buffers[0];
2635141cc406Sopenharmony_ci	  dev->info.wanted_bufsize = bufsize[0];
2636141cc406Sopenharmony_ci	  dev->info.queued_reads = queued_reads[0];
2637141cc406Sopenharmony_ci	}
2638141cc406Sopenharmony_ci    }
2639141cc406Sopenharmony_ci  else
2640141cc406Sopenharmony_ci    {
2641141cc406Sopenharmony_ci      dev = first_dev;
2642141cc406Sopenharmony_ci    }
2643141cc406Sopenharmony_ci
2644141cc406Sopenharmony_ci  if (!dev)
2645141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
2646141cc406Sopenharmony_ci
2647141cc406Sopenharmony_ci  s = malloc (sizeof (*s));
2648141cc406Sopenharmony_ci  if (!s)
2649141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
2650141cc406Sopenharmony_ci  memset (s, 0, sizeof (*s));
2651141cc406Sopenharmony_ci
2652141cc406Sopenharmony_ci  s->fd = -1;
2653141cc406Sopenharmony_ci  s->dev = dev;
2654141cc406Sopenharmony_ci
2655141cc406Sopenharmony_ci  s->buffer = 0;
2656141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2657141cc406Sopenharmony_ci  for (i = 0; i < 4; ++i)
2658141cc406Sopenharmony_ci    for (j = 0; j < 256; ++j)
2659141cc406Sopenharmony_ci      s->gamma_table[i][j] = j;
2660141cc406Sopenharmony_ci#endif
2661141cc406Sopenharmony_ci  status = init_options (s);
2662141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
2663141cc406Sopenharmony_ci    {
2664141cc406Sopenharmony_ci      /* xxx clean up mallocs */
2665141cc406Sopenharmony_ci      return status;
2666141cc406Sopenharmony_ci    }
2667141cc406Sopenharmony_ci
2668141cc406Sopenharmony_ci  s->next = first_handle;
2669141cc406Sopenharmony_ci  first_handle = s;
2670141cc406Sopenharmony_ci
2671141cc406Sopenharmony_ci  *handle = s;
2672141cc406Sopenharmony_ci
2673141cc406Sopenharmony_ci  DBG (10, ">>\n");
2674141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
2675141cc406Sopenharmony_ci}
2676141cc406Sopenharmony_ci
2677141cc406Sopenharmony_civoid
2678141cc406Sopenharmony_cisane_close (SANE_Handle handle)
2679141cc406Sopenharmony_ci{
2680141cc406Sopenharmony_ci  SHARP_Scanner *s = (SHARP_Scanner *) handle;
2681141cc406Sopenharmony_ci  DBG (10, "<< sane_close ");
2682141cc406Sopenharmony_ci
2683141cc406Sopenharmony_ci  if (s->fd != -1)
2684141cc406Sopenharmony_ci    sanei_scsi_close (s->fd);
2685141cc406Sopenharmony_ci#ifdef USE_FORK
2686141cc406Sopenharmony_ci  {
2687141cc406Sopenharmony_ci    struct shmid_ds ds;
2688141cc406Sopenharmony_ci    if (s->shmid != -1)
2689141cc406Sopenharmony_ci      shmctl(s->shmid, IPC_RMID, &ds);
2690141cc406Sopenharmony_ci  }
2691141cc406Sopenharmony_ci#endif
2692141cc406Sopenharmony_ci  if (s->buffer)
2693141cc406Sopenharmony_ci    free(s->buffer);
2694141cc406Sopenharmony_ci  free (s);
2695141cc406Sopenharmony_ci
2696141cc406Sopenharmony_ci  DBG (10, ">>\n");
2697141cc406Sopenharmony_ci}
2698141cc406Sopenharmony_ci
2699141cc406Sopenharmony_ciconst SANE_Option_Descriptor *
2700141cc406Sopenharmony_cisane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2701141cc406Sopenharmony_ci{
2702141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
2703141cc406Sopenharmony_ci  DBG (10, "<< sane_get_option_descriptor ");
2704141cc406Sopenharmony_ci
2705141cc406Sopenharmony_ci  if ((unsigned) option >= NUM_OPTIONS)
2706141cc406Sopenharmony_ci    return (0);
2707141cc406Sopenharmony_ci
2708141cc406Sopenharmony_ci  DBG (10, ">>\n");
2709141cc406Sopenharmony_ci  return (s->opt + option);
2710141cc406Sopenharmony_ci}
2711141cc406Sopenharmony_ci
2712141cc406Sopenharmony_ciSANE_Status
2713141cc406Sopenharmony_cisane_control_option (SANE_Handle handle, SANE_Int option,
2714141cc406Sopenharmony_ci		     SANE_Action action, void *val, SANE_Int * info)
2715141cc406Sopenharmony_ci{
2716141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
2717141cc406Sopenharmony_ci  SANE_Status status;
2718141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2719141cc406Sopenharmony_ci  SANE_Word w, cap;
2720141cc406Sopenharmony_ci#else
2721141cc406Sopenharmony_ci  SANE_Word cap;
2722141cc406Sopenharmony_ci#endif
2723141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST
2724141cc406Sopenharmony_ci  int i;
2725141cc406Sopenharmony_ci#endif
2726141cc406Sopenharmony_ci  int range_index;
2727141cc406Sopenharmony_ci  DBG (10, "<< sane_control_option %i", option);
2728141cc406Sopenharmony_ci
2729141cc406Sopenharmony_ci  if (info)
2730141cc406Sopenharmony_ci    *info = 0;
2731141cc406Sopenharmony_ci
2732141cc406Sopenharmony_ci  if (s->scanning)
2733141cc406Sopenharmony_ci    return (SANE_STATUS_DEVICE_BUSY);
2734141cc406Sopenharmony_ci  if (option >= NUM_OPTIONS)
2735141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
2736141cc406Sopenharmony_ci
2737141cc406Sopenharmony_ci  cap = s->opt[option].cap;
2738141cc406Sopenharmony_ci  if (!SANE_OPTION_IS_ACTIVE (cap))
2739141cc406Sopenharmony_ci    return (SANE_STATUS_INVAL);
2740141cc406Sopenharmony_ci
2741141cc406Sopenharmony_ci  if (action == SANE_ACTION_GET_VALUE)
2742141cc406Sopenharmony_ci    {
2743141cc406Sopenharmony_ci      switch (option)
2744141cc406Sopenharmony_ci	{
2745141cc406Sopenharmony_ci	  /* word options: */
2746141cc406Sopenharmony_ci	case OPT_X_RESOLUTION:
2747141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
2748141cc406Sopenharmony_ci	case OPT_Y_RESOLUTION:
2749141cc406Sopenharmony_ci#endif
2750141cc406Sopenharmony_ci	case OPT_TL_X:
2751141cc406Sopenharmony_ci	case OPT_TL_Y:
2752141cc406Sopenharmony_ci	case OPT_BR_X:
2753141cc406Sopenharmony_ci	case OPT_BR_Y:
2754141cc406Sopenharmony_ci	case OPT_NUM_OPTS:
2755141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2756141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2757141cc406Sopenharmony_ci	case OPT_THRESHOLD_R:
2758141cc406Sopenharmony_ci	case OPT_THRESHOLD_G:
2759141cc406Sopenharmony_ci	case OPT_THRESHOLD_B:
2760141cc406Sopenharmony_ci#endif
2761141cc406Sopenharmony_ci	case OPT_SPEED:
2762141cc406Sopenharmony_ci	case OPT_PREVIEW:
2763141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2764141cc406Sopenharmony_ci	case OPT_CUSTOM_GAMMA:
2765141cc406Sopenharmony_ci#endif
2766141cc406Sopenharmony_ci	  *(SANE_Word *) val = s->val[option].w;
2767141cc406Sopenharmony_ci#if 0 /* here, values are read; reload should not be necessary */
2768141cc406Sopenharmony_ci	  if (info)
2769141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_PARAMS;
2770141cc406Sopenharmony_ci#endif
2771141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2772141cc406Sopenharmony_ci
2773141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2774141cc406Sopenharmony_ci	  /* word-array options: */
2775141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR:
2776141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_R:
2777141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_G:
2778141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_B:
2779141cc406Sopenharmony_ci	  memcpy (val, s->val[option].wa, s->opt[option].size);
2780141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
2781141cc406Sopenharmony_ci#endif
2782141cc406Sopenharmony_ci
2783141cc406Sopenharmony_ci	  /* string options: */
2784141cc406Sopenharmony_ci	case OPT_MODE:
2785141cc406Sopenharmony_ci	case OPT_HALFTONE:
2786141cc406Sopenharmony_ci	case OPT_PAPER:
2787141cc406Sopenharmony_ci	case OPT_GAMMA:
2788141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST
2789141cc406Sopenharmony_ci	case OPT_RESOLUTION_LIST:
2790141cc406Sopenharmony_ci#endif
2791141cc406Sopenharmony_ci	case OPT_EDGE_EMPHASIS:
2792141cc406Sopenharmony_ci	case OPT_LIGHTCOLOR:
2793141cc406Sopenharmony_ci	case OPT_SCANSOURCE:
2794141cc406Sopenharmony_ci	  strcpy (val, s->val[option].s);
2795141cc406Sopenharmony_ci#if 0
2796141cc406Sopenharmony_ci	  if (info)
2797141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_PARAMS;
2798141cc406Sopenharmony_ci#endif
2799141cc406Sopenharmony_ci
2800141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2801141cc406Sopenharmony_ci
2802141cc406Sopenharmony_ci	}
2803141cc406Sopenharmony_ci    }
2804141cc406Sopenharmony_ci  else if (action == SANE_ACTION_SET_VALUE)
2805141cc406Sopenharmony_ci    {
2806141cc406Sopenharmony_ci      if (!SANE_OPTION_IS_SETTABLE (cap))
2807141cc406Sopenharmony_ci	return (SANE_STATUS_INVAL);
2808141cc406Sopenharmony_ci
2809141cc406Sopenharmony_ci      status = sanei_constrain_value (s->opt + option, val, info);
2810141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
2811141cc406Sopenharmony_ci	return status;
2812141cc406Sopenharmony_ci
2813141cc406Sopenharmony_ci      switch (option)
2814141cc406Sopenharmony_ci	{
2815141cc406Sopenharmony_ci	  /* (mostly) side-effect-free word options: */
2816141cc406Sopenharmony_ci	case OPT_X_RESOLUTION:
2817141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
2818141cc406Sopenharmony_ci	case OPT_Y_RESOLUTION:
2819141cc406Sopenharmony_ci#endif
2820141cc406Sopenharmony_ci	case OPT_TL_X:
2821141cc406Sopenharmony_ci	case OPT_TL_Y:
2822141cc406Sopenharmony_ci	case OPT_BR_X:
2823141cc406Sopenharmony_ci	case OPT_BR_Y:
2824141cc406Sopenharmony_ci	  if (info && s->val[option].w != *(SANE_Word *) val)
2825141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_PARAMS;
2826141cc406Sopenharmony_ci          // fall through
2827141cc406Sopenharmony_ci	case OPT_NUM_OPTS:
2828141cc406Sopenharmony_ci	case OPT_THRESHOLD:
2829141cc406Sopenharmony_ci	  /* xxx theoretically, we could use OPT_THRESHOLD in
2830141cc406Sopenharmony_ci	     bi-level color mode to adjust all three other
2831141cc406Sopenharmony_ci	     threshold together. But this would require to set
2832141cc406Sopenharmony_ci	     the bit SANE_INFO_RELOAD_OPTIONS in *info, and that
2833141cc406Sopenharmony_ci	     would unfortunately cause a crash in both xscanimage
2834141cc406Sopenharmony_ci	     and xsane... Therefore, OPT_THRESHOLD is disabled
2835141cc406Sopenharmony_ci	     for bi-level color scan right now.
2836141cc406Sopenharmony_ci	  */
2837141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2838141cc406Sopenharmony_ci	case OPT_THRESHOLD_R:
2839141cc406Sopenharmony_ci	case OPT_THRESHOLD_G:
2840141cc406Sopenharmony_ci	case OPT_THRESHOLD_B:
2841141cc406Sopenharmony_ci#endif
2842141cc406Sopenharmony_ci	case OPT_SPEED:
2843141cc406Sopenharmony_ci	case OPT_PREVIEW:
2844141cc406Sopenharmony_ci	  s->val[option].w = *(SANE_Word *) val;
2845141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2846141cc406Sopenharmony_ci
2847141cc406Sopenharmony_ci
2848141cc406Sopenharmony_ci	case OPT_MODE:
2849141cc406Sopenharmony_ci	  if (strcmp (val, M_LINEART) == 0)
2850141cc406Sopenharmony_ci	    {
2851141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
2852141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2853141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE;
2854141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE;
2855141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE;
2856141cc406Sopenharmony_ci#endif
2857141cc406Sopenharmony_ci	      if (s->dev->sensedat.model == JX330)
2858141cc406Sopenharmony_ci                s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
2859141cc406Sopenharmony_ci	    }
2860141cc406Sopenharmony_ci	  else if (strcmp (val, M_LINEART_COLOR) == 0)
2861141cc406Sopenharmony_ci	    {
2862141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2863141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2864141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_R].cap &= ~SANE_CAP_INACTIVE;
2865141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_G].cap &= ~SANE_CAP_INACTIVE;
2866141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_B].cap &= ~SANE_CAP_INACTIVE;
2867141cc406Sopenharmony_ci#endif
2868141cc406Sopenharmony_ci	      if (s->dev->sensedat.model == JX330)
2869141cc406Sopenharmony_ci                s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
2870141cc406Sopenharmony_ci	    }
2871141cc406Sopenharmony_ci	  else
2872141cc406Sopenharmony_ci	    {
2873141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2874141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
2875141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE;
2876141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE;
2877141cc406Sopenharmony_ci	      s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE;
2878141cc406Sopenharmony_ci#endif
2879141cc406Sopenharmony_ci              s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
2880141cc406Sopenharmony_ci            }
2881141cc406Sopenharmony_ci
2882141cc406Sopenharmony_ci	  if (   strcmp (val, M_LINEART) == 0
2883141cc406Sopenharmony_ci	      || strcmp (val, M_GRAY) == 0)
2884141cc406Sopenharmony_ci            {
2885141cc406Sopenharmony_ci	      s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE;
2886141cc406Sopenharmony_ci            }
2887141cc406Sopenharmony_ci          else
2888141cc406Sopenharmony_ci            {
2889141cc406Sopenharmony_ci	      s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE;
2890141cc406Sopenharmony_ci            }
2891141cc406Sopenharmony_ci
2892141cc406Sopenharmony_ci          strcpy(s->val[option].s, val);
2893141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
2894141cc406Sopenharmony_ci          set_gamma_caps(s);
2895141cc406Sopenharmony_ci#endif
2896141cc406Sopenharmony_ci          if (info)
2897141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2898141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2899141cc406Sopenharmony_ci
2900141cc406Sopenharmony_ci	case OPT_GAMMA:
2901141cc406Sopenharmony_ci	case OPT_HALFTONE:
2902141cc406Sopenharmony_ci	case OPT_EDGE_EMPHASIS:
2903141cc406Sopenharmony_ci	case OPT_LIGHTCOLOR:
2904141cc406Sopenharmony_ci#if 0
2905141cc406Sopenharmony_ci	  if (s->val[option].s)
2906141cc406Sopenharmony_ci	    free (s->val[option].s);
2907141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2908141cc406Sopenharmony_ci#endif
2909141cc406Sopenharmony_ci          strcpy(s->val[option].s, val);
2910141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2911141cc406Sopenharmony_ci
2912141cc406Sopenharmony_ci	case OPT_SCANSOURCE:
2913141cc406Sopenharmony_ci	  if (info && strcmp (s->val[option].s, (SANE_String) val))
2914141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2915141cc406Sopenharmony_ci#if 0
2916141cc406Sopenharmony_ci	  if (s->val[option].s)
2917141cc406Sopenharmony_ci	    free (s->val[option].s);
2918141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2919141cc406Sopenharmony_ci#endif
2920141cc406Sopenharmony_ci          strcpy(s->val[option].s, val);
2921141cc406Sopenharmony_ci	  if (strcmp(val, use_fsu) == 0)
2922141cc406Sopenharmony_ci	    range_index = SCAN_WITH_FSU;
2923141cc406Sopenharmony_ci	  else if (strcmp(val, use_adf) == 0)
2924141cc406Sopenharmony_ci	    range_index = SCAN_WITH_ADF;
2925141cc406Sopenharmony_ci	  else
2926141cc406Sopenharmony_ci	    range_index = SCAN_SIMPLE;
2927141cc406Sopenharmony_ci
2928141cc406Sopenharmony_ci          s->opt[OPT_TL_X].constraint.range
2929141cc406Sopenharmony_ci            = &s->dev->info.tl_x_ranges[range_index];
2930141cc406Sopenharmony_ci          clip_value (&s->opt[OPT_TL_X], &s->val[OPT_TL_X].w);
2931141cc406Sopenharmony_ci
2932141cc406Sopenharmony_ci          s->opt[OPT_TL_Y].constraint.range
2933141cc406Sopenharmony_ci            = &s->dev->info.tl_y_ranges[range_index];
2934141cc406Sopenharmony_ci          clip_value (&s->opt[OPT_TL_Y], &s->val[OPT_TL_Y].w);
2935141cc406Sopenharmony_ci
2936141cc406Sopenharmony_ci          s->opt[OPT_BR_X].constraint.range
2937141cc406Sopenharmony_ci            = &s->dev->info.br_x_ranges[range_index];
2938141cc406Sopenharmony_ci          clip_value (&s->opt[OPT_BR_X], &s->val[OPT_BR_X].w);
2939141cc406Sopenharmony_ci
2940141cc406Sopenharmony_ci          s->opt[OPT_BR_Y].constraint.range
2941141cc406Sopenharmony_ci            = &s->dev->info.br_y_ranges[range_index];
2942141cc406Sopenharmony_ci          clip_value (&s->opt[OPT_BR_Y], &s->val[OPT_BR_Y].w);
2943141cc406Sopenharmony_ci
2944141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2945141cc406Sopenharmony_ci
2946141cc406Sopenharmony_ci	case OPT_PAPER:
2947141cc406Sopenharmony_ci          if (info)
2948141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2949141cc406Sopenharmony_ci#if 0
2950141cc406Sopenharmony_ci	  if (s->val[option].s)
2951141cc406Sopenharmony_ci	    free (s->val[option].s);
2952141cc406Sopenharmony_ci	  s->val[option].s = strdup (val);
2953141cc406Sopenharmony_ci#endif
2954141cc406Sopenharmony_ci          strcpy(s->val[option].s, val);
2955141cc406Sopenharmony_ci	  s->val[OPT_TL_X].w = SANE_FIX(0);
2956141cc406Sopenharmony_ci	  s->val[OPT_TL_Y].w = SANE_FIX(0);
2957141cc406Sopenharmony_ci	  if (strcmp (s->val[option].s, "A3") == 0){
2958141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(297);
2959141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(420);
2960141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "A4") == 0){
2961141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(210);
2962141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(297);
2963141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "A5") == 0){
2964141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(148.5);
2965141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(210);
2966141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "A6") == 0){
2967141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(105);
2968141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(148.5);
2969141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "B4") == 0){
2970141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(250);
2971141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(353);
2972141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "B5") == 0){
2973141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(182);
2974141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(257);
2975141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, W_LETTER) == 0){
2976141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(279.4);
2977141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(431.8);
2978141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "Legal") == 0){
2979141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(215.9);
2980141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(355.6);
2981141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, "Letter") == 0){
2982141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(215.9);
2983141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(279.4);
2984141cc406Sopenharmony_ci	  }else if (strcmp (s->val[option].s, INVOICE) == 0){
2985141cc406Sopenharmony_ci	      s->val[OPT_BR_X].w = SANE_FIX(215.9);
2986141cc406Sopenharmony_ci	      s->val[OPT_BR_Y].w = SANE_FIX(139.7);
2987141cc406Sopenharmony_ci	  }else{
2988141cc406Sopenharmony_ci	  }
2989141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
2990141cc406Sopenharmony_ci
2991141cc406Sopenharmony_ci#ifdef USE_RESOLUTION_LIST
2992141cc406Sopenharmony_ci	case OPT_RESOLUTION_LIST:
2993141cc406Sopenharmony_ci	  if (info)
2994141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2995141cc406Sopenharmony_ci	  for (i = 0; s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]; i++) {
2996141cc406Sopenharmony_ci	    if (strcmp (val,
2997141cc406Sopenharmony_ci	          s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]) == 0){
2998141cc406Sopenharmony_ci	      s->val[OPT_X_RESOLUTION].w
2999141cc406Sopenharmony_ci	        = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]);
3000141cc406Sopenharmony_ci	      s->val[OPT_Y_RESOLUTION].w
3001141cc406Sopenharmony_ci	        = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]);
3002141cc406Sopenharmony_ci	      if (info)
3003141cc406Sopenharmony_ci	        *info |= SANE_INFO_RELOAD_PARAMS;
3004141cc406Sopenharmony_ci	      break;
3005141cc406Sopenharmony_ci	    }
3006141cc406Sopenharmony_ci	  }
3007141cc406Sopenharmony_ci	  return (SANE_STATUS_GOOD);
3008141cc406Sopenharmony_ci#endif
3009141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
3010141cc406Sopenharmony_ci	  /* side-effect-free word-array options: */
3011141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR:
3012141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_R:
3013141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_G:
3014141cc406Sopenharmony_ci	case OPT_GAMMA_VECTOR_B:
3015141cc406Sopenharmony_ci	  memcpy (s->val[option].wa, val, s->opt[option].size);
3016141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
3017141cc406Sopenharmony_ci
3018141cc406Sopenharmony_ci	case OPT_CUSTOM_GAMMA:
3019141cc406Sopenharmony_ci	  w = *(SANE_Word *) val;
3020141cc406Sopenharmony_ci
3021141cc406Sopenharmony_ci	  if (w == s->val[OPT_CUSTOM_GAMMA].w)
3022141cc406Sopenharmony_ci	    return SANE_STATUS_GOOD;		/* no change */
3023141cc406Sopenharmony_ci
3024141cc406Sopenharmony_ci	  if (info)
3025141cc406Sopenharmony_ci	    *info |= SANE_INFO_RELOAD_OPTIONS;
3026141cc406Sopenharmony_ci	  s->val[OPT_CUSTOM_GAMMA].w = w;
3027141cc406Sopenharmony_ci          set_gamma_caps(s);
3028141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
3029141cc406Sopenharmony_ci#endif
3030141cc406Sopenharmony_ci	}
3031141cc406Sopenharmony_ci    }
3032141cc406Sopenharmony_ci
3033141cc406Sopenharmony_ci  DBG (10, ">>\n");
3034141cc406Sopenharmony_ci  return (SANE_STATUS_INVAL);
3035141cc406Sopenharmony_ci}
3036141cc406Sopenharmony_ci
3037141cc406Sopenharmony_ciSANE_Status
3038141cc406Sopenharmony_cisane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
3039141cc406Sopenharmony_ci{
3040141cc406Sopenharmony_ci  int width, length, xres, yres;
3041141cc406Sopenharmony_ci  const char *mode;
3042141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
3043141cc406Sopenharmony_ci  DBG (10, "<< sane_get_parameters ");
3044141cc406Sopenharmony_ci
3045141cc406Sopenharmony_ci  xres = s->val[OPT_X_RESOLUTION].w;
3046141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
3047141cc406Sopenharmony_ci  yres = s->val[OPT_Y_RESOLUTION].w;
3048141cc406Sopenharmony_ci#else
3049141cc406Sopenharmony_ci  yres = xres;
3050141cc406Sopenharmony_ci#endif
3051141cc406Sopenharmony_ci  if (!s->scanning)
3052141cc406Sopenharmony_ci    {
3053141cc406Sopenharmony_ci      /* make best-effort guess at what parameters will look like once
3054141cc406Sopenharmony_ci         scanning starts.  */
3055141cc406Sopenharmony_ci      memset (&s->params, 0, sizeof (s->params));
3056141cc406Sopenharmony_ci
3057141cc406Sopenharmony_ci      width = MM_TO_PIX(  SANE_UNFIX(s->val[OPT_BR_X].w)
3058141cc406Sopenharmony_ci                        - SANE_UNFIX(s->val[OPT_TL_X].w),
3059141cc406Sopenharmony_ci			s->dev->info.mud);
3060141cc406Sopenharmony_ci      length = MM_TO_PIX(  SANE_UNFIX(s->val[OPT_BR_Y].w)
3061141cc406Sopenharmony_ci                          - SANE_UNFIX(s->val[OPT_TL_Y].w),
3062141cc406Sopenharmony_ci			 s->dev->info.mud);
3063141cc406Sopenharmony_ci
3064141cc406Sopenharmony_ci      s->width = width;
3065141cc406Sopenharmony_ci      s->length = length;
3066141cc406Sopenharmony_ci      s->params.pixels_per_line = width * xres / s->dev->info.mud;
3067141cc406Sopenharmony_ci      s->params.lines = length * yres / s->dev->info.mud;
3068141cc406Sopenharmony_ci      s->unscanned_lines = s->params.lines;
3069141cc406Sopenharmony_ci    }
3070141cc406Sopenharmony_ci  else
3071141cc406Sopenharmony_ci    {
3072141cc406Sopenharmony_ci      static u_char cmd[] = {READ, 0, 0x81, 0, 0, 0, 0, 0, 4, 0};
3073141cc406Sopenharmony_ci      static u_char buf[4];
3074141cc406Sopenharmony_ci      size_t len = 4;
3075141cc406Sopenharmony_ci      SANE_Status status;
3076141cc406Sopenharmony_ci
3077141cc406Sopenharmony_ci      /* if async reads are used, )ie. if USE_FORK is defined,
3078141cc406Sopenharmony_ci         this command may only be issued immediately after the
3079141cc406Sopenharmony_ci         "start scan" command. Later calls will confuse the
3080141cc406Sopenharmony_ci         read queue.
3081141cc406Sopenharmony_ci      */
3082141cc406Sopenharmony_ci      if (!s->get_params_called)
3083141cc406Sopenharmony_ci        {
3084141cc406Sopenharmony_ci          wait_ready(s->fd);
3085141cc406Sopenharmony_ci          status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), buf, &len);
3086141cc406Sopenharmony_ci
3087141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
3088141cc406Sopenharmony_ci            {
3089141cc406Sopenharmony_ci              do_cancel(s);
3090141cc406Sopenharmony_ci              return (status);
3091141cc406Sopenharmony_ci            }
3092141cc406Sopenharmony_ci          s->params.pixels_per_line = (buf[1] << 8) + buf[0];
3093141cc406Sopenharmony_ci          s->params.lines = (buf[3] << 8) + buf[2];
3094141cc406Sopenharmony_ci          s->get_params_called = 1;
3095141cc406Sopenharmony_ci        }
3096141cc406Sopenharmony_ci    }
3097141cc406Sopenharmony_ci
3098141cc406Sopenharmony_ci  xres = s->val[OPT_X_RESOLUTION].w;
3099141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
3100141cc406Sopenharmony_ci  yres = s->val[OPT_Y_RESOLUTION].w;
3101141cc406Sopenharmony_ci#else
3102141cc406Sopenharmony_ci  yres = xres;
3103141cc406Sopenharmony_ci#endif
3104141cc406Sopenharmony_ci
3105141cc406Sopenharmony_ci  mode = s->val[OPT_MODE].s;
3106141cc406Sopenharmony_ci
3107141cc406Sopenharmony_ci  if (strcmp (mode, M_LINEART) == 0)
3108141cc406Sopenharmony_ci     {
3109141cc406Sopenharmony_ci       s->params.format = SANE_FRAME_GRAY;
3110141cc406Sopenharmony_ci       s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
3111141cc406Sopenharmony_ci       s->params.depth = 1;
3112141cc406Sopenharmony_ci       s->modes = MODES_LINEART;
3113141cc406Sopenharmony_ci     }
3114141cc406Sopenharmony_ci  else if (strcmp (mode, M_GRAY) == 0)
3115141cc406Sopenharmony_ci     {
3116141cc406Sopenharmony_ci       s->params.format = SANE_FRAME_GRAY;
3117141cc406Sopenharmony_ci       s->params.bytes_per_line = s->params.pixels_per_line;
3118141cc406Sopenharmony_ci       s->params.depth = 8;
3119141cc406Sopenharmony_ci       s->modes = MODES_GRAY;
3120141cc406Sopenharmony_ci     }
3121141cc406Sopenharmony_ci  else
3122141cc406Sopenharmony_ci     {
3123141cc406Sopenharmony_ci       s->params.format = SANE_FRAME_RGB;
3124141cc406Sopenharmony_ci       s->params.bytes_per_line = 3 * s->params.pixels_per_line;
3125141cc406Sopenharmony_ci       s->params.depth = 8;
3126141cc406Sopenharmony_ci       s->modes = MODES_COLOR;
3127141cc406Sopenharmony_ci     }
3128141cc406Sopenharmony_ci  s->params.last_frame = SANE_TRUE;
3129141cc406Sopenharmony_ci
3130141cc406Sopenharmony_ci  if (params)
3131141cc406Sopenharmony_ci    *params = s->params;
3132141cc406Sopenharmony_ci
3133141cc406Sopenharmony_ci  DBG (10, ">>\n");
3134141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
3135141cc406Sopenharmony_ci}
3136141cc406Sopenharmony_ci
3137141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
3138141cc406Sopenharmony_ci
3139141cc406Sopenharmony_cistatic int
3140141cc406Sopenharmony_cisprint_gamma(Option_Value val, SANE_Byte *dst)
3141141cc406Sopenharmony_ci{
3142141cc406Sopenharmony_ci  int i;
3143141cc406Sopenharmony_ci  SANE_Byte *p = dst;
3144141cc406Sopenharmony_ci
3145141cc406Sopenharmony_ci  p += sprintf((char *) p, "%i", val.wa[0] > 255 ? 255 : val.wa[0]);
3146141cc406Sopenharmony_ci  /* val.wa[i] is over 255, so val.wa[i] is limited to 255 */
3147141cc406Sopenharmony_ci  for (i = 1; i < 256; i++)
3148141cc406Sopenharmony_ci    p += sprintf((char *) p, ",%i", val.wa[i] > 255 ? 255 : val.wa[i]);
3149141cc406Sopenharmony_ci  return p - dst;
3150141cc406Sopenharmony_ci}
3151141cc406Sopenharmony_ci
3152141cc406Sopenharmony_cistatic SANE_Status
3153141cc406Sopenharmony_cisend_ascii_gamma_tables (SHARP_Scanner *s)
3154141cc406Sopenharmony_ci{
3155141cc406Sopenharmony_ci  SANE_Status status;
3156141cc406Sopenharmony_ci  int i;
3157141cc406Sopenharmony_ci
3158141cc406Sopenharmony_ci  DBG(11, "<< send_ascii_gamma_tables ");
3159141cc406Sopenharmony_ci
3160141cc406Sopenharmony_ci  /* we need: 4 bytes for each gamma value (3 digits + delimiter)
3161141cc406Sopenharmony_ci             + 10 bytes for the command header
3162141cc406Sopenharmony_ci     i.e. 4 * 4 * 256 + 10 = 4106 bytes
3163141cc406Sopenharmony_ci  */
3164141cc406Sopenharmony_ci
3165141cc406Sopenharmony_ci  if (s->dev->info.bufsize < 4106)
3166141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
3167141cc406Sopenharmony_ci
3168141cc406Sopenharmony_ci  memset(s->buffer, 0, 4106);
3169141cc406Sopenharmony_ci
3170141cc406Sopenharmony_ci  i = sprint_gamma(s->val[OPT_GAMMA_VECTOR_R], &s->buffer[10]);
3171141cc406Sopenharmony_ci  s->buffer[10+i++] = '/';
3172141cc406Sopenharmony_ci  i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_G], &s->buffer[10+i]);
3173141cc406Sopenharmony_ci  s->buffer[10+i++] = '/';
3174141cc406Sopenharmony_ci  i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_B], &s->buffer[10+i]);
3175141cc406Sopenharmony_ci  s->buffer[10+i++] = '/';
3176141cc406Sopenharmony_ci  i += sprint_gamma(s->val[OPT_GAMMA_VECTOR], &s->buffer[10+i]);
3177141cc406Sopenharmony_ci
3178141cc406Sopenharmony_ci  DBG(11, "%s\n", &s->buffer[10]);
3179141cc406Sopenharmony_ci
3180141cc406Sopenharmony_ci  s->buffer[0] = SEND;
3181141cc406Sopenharmony_ci  s->buffer[2] = 0x03;
3182141cc406Sopenharmony_ci  s->buffer[7] = i >> 8;
3183141cc406Sopenharmony_ci  s->buffer[8] = i & 0xff;
3184141cc406Sopenharmony_ci
3185141cc406Sopenharmony_ci  wait_ready(s->fd);
3186141cc406Sopenharmony_ci  status = sanei_scsi_cmd (s->fd, s->buffer, i+10, 0, 0);
3187141cc406Sopenharmony_ci
3188141cc406Sopenharmony_ci  DBG(11, ">>\n");
3189141cc406Sopenharmony_ci
3190141cc406Sopenharmony_ci  return status;
3191141cc406Sopenharmony_ci}
3192141cc406Sopenharmony_ci#endif
3193141cc406Sopenharmony_ci
3194141cc406Sopenharmony_cistatic SANE_Status
3195141cc406Sopenharmony_cisend_binary_g_table(SHARP_Scanner *s, SANE_Word *a, int dtq)
3196141cc406Sopenharmony_ci{
3197141cc406Sopenharmony_ci  SANE_Status status;
3198141cc406Sopenharmony_ci  int i;
3199141cc406Sopenharmony_ci
3200141cc406Sopenharmony_ci  DBG(11, "<< send_binary_g_table\n");
3201141cc406Sopenharmony_ci
3202141cc406Sopenharmony_ci  memset(s->buffer, 0, 522);
3203141cc406Sopenharmony_ci
3204141cc406Sopenharmony_ci  s->buffer[0] = SEND;
3205141cc406Sopenharmony_ci  s->buffer[2] = 0x03;
3206141cc406Sopenharmony_ci  s->buffer[5] = dtq;
3207141cc406Sopenharmony_ci  s->buffer[7] = 2;
3208141cc406Sopenharmony_ci  s->buffer[8] = 0;
3209141cc406Sopenharmony_ci
3210141cc406Sopenharmony_ci  for (i = 0; i < 256; i++)
3211141cc406Sopenharmony_ci    {
3212141cc406Sopenharmony_ci      s->buffer[2*i+11] = a[i] > 255 ? 255 : a[i];
3213141cc406Sopenharmony_ci    }
3214141cc406Sopenharmony_ci
3215141cc406Sopenharmony_ci  for (i = 0; i < 256; i += 16)
3216141cc406Sopenharmony_ci    {
3217141cc406Sopenharmony_ci      DBG(11, "%02x %02x %02x %02x %02x %02x %02x %02x "
3218141cc406Sopenharmony_ci              "%02x %02x %02x %02x %02x %02x %02x %02x\n",
3219141cc406Sopenharmony_ci              a[i  ], a[i+1], a[i+2], a[i+3],
3220141cc406Sopenharmony_ci              a[i+4], a[i+5], a[i+6], a[i+7],
3221141cc406Sopenharmony_ci              a[i+8], a[i+9], a[i+10], a[i+11],
3222141cc406Sopenharmony_ci              a[i+12], a[i+13], a[i+14], a[i+15]);
3223141cc406Sopenharmony_ci    }
3224141cc406Sopenharmony_ci
3225141cc406Sopenharmony_ci  wait_ready(s->fd);
3226141cc406Sopenharmony_ci  status = sanei_scsi_cmd (s->fd, s->buffer, 2*i+10, 0, 0);
3227141cc406Sopenharmony_ci
3228141cc406Sopenharmony_ci  DBG(11, ">>\n");
3229141cc406Sopenharmony_ci
3230141cc406Sopenharmony_ci  return status;
3231141cc406Sopenharmony_ci}
3232141cc406Sopenharmony_ci
3233141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
3234141cc406Sopenharmony_cistatic SANE_Status
3235141cc406Sopenharmony_cisend_binary_gamma_tables (SHARP_Scanner *s)
3236141cc406Sopenharmony_ci{
3237141cc406Sopenharmony_ci  SANE_Status status;
3238141cc406Sopenharmony_ci
3239141cc406Sopenharmony_ci  status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR].wa, 0x10);
3240141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3241141cc406Sopenharmony_ci    return status;
3242141cc406Sopenharmony_ci
3243141cc406Sopenharmony_ci  status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_R].wa, 0x11);
3244141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3245141cc406Sopenharmony_ci    return status;
3246141cc406Sopenharmony_ci
3247141cc406Sopenharmony_ci  status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_G].wa, 0x12);
3248141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3249141cc406Sopenharmony_ci    return status;
3250141cc406Sopenharmony_ci
3251141cc406Sopenharmony_ci  status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_B].wa, 0x13);
3252141cc406Sopenharmony_ci
3253141cc406Sopenharmony_ci  return status;
3254141cc406Sopenharmony_ci}
3255141cc406Sopenharmony_ci
3256141cc406Sopenharmony_cistatic SANE_Status
3257141cc406Sopenharmony_cisend_gamma_tables (SHARP_Scanner *s)
3258141cc406Sopenharmony_ci{
3259141cc406Sopenharmony_ci  if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350)
3260141cc406Sopenharmony_ci    {
3261141cc406Sopenharmony_ci      return send_ascii_gamma_tables(s);
3262141cc406Sopenharmony_ci    }
3263141cc406Sopenharmony_ci  else
3264141cc406Sopenharmony_ci    {
3265141cc406Sopenharmony_ci      return send_binary_gamma_tables(s);
3266141cc406Sopenharmony_ci    }
3267141cc406Sopenharmony_ci
3268141cc406Sopenharmony_ci}
3269141cc406Sopenharmony_ci#endif
3270141cc406Sopenharmony_ci
3271141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
3272141cc406Sopenharmony_cistatic SANE_Status
3273141cc406Sopenharmony_cisend_threshold_data(SHARP_Scanner *s)
3274141cc406Sopenharmony_ci{
3275141cc406Sopenharmony_ci  SANE_Status status;
3276141cc406Sopenharmony_ci  SANE_Byte cmd[26] = {SEND, 0, 0x82, 0, 0, 0, 0, 0, 0, 0};
3277141cc406Sopenharmony_ci  int len;
3278141cc406Sopenharmony_ci
3279141cc406Sopenharmony_ci  memset(cmd, 0, sizeof(cmd));
3280141cc406Sopenharmony_ci  /* maximum string length: 3 bytes for each number (they are
3281141cc406Sopenharmony_ci     restricted to the range 0..255), 3 '/' and the null-byte,
3282141cc406Sopenharmony_ci     total: 16 bytes.
3283141cc406Sopenharmony_ci  */
3284141cc406Sopenharmony_ci  len = sprintf((char *) &cmd[10], "%i/%i/%i/%i",
3285141cc406Sopenharmony_ci                s->val[OPT_THRESHOLD_R].w,
3286141cc406Sopenharmony_ci                s->val[OPT_THRESHOLD_G].w,
3287141cc406Sopenharmony_ci                s->val[OPT_THRESHOLD_B].w,
3288141cc406Sopenharmony_ci                s->val[OPT_THRESHOLD].w);
3289141cc406Sopenharmony_ci  cmd[8] = len;
3290141cc406Sopenharmony_ci
3291141cc406Sopenharmony_ci  wait_ready(s->fd);
3292141cc406Sopenharmony_ci  status = sanei_scsi_cmd(s->fd, cmd, len + 10, 0, 0);
3293141cc406Sopenharmony_ci  return status;
3294141cc406Sopenharmony_ci}
3295141cc406Sopenharmony_ci#endif
3296141cc406Sopenharmony_ci
3297141cc406Sopenharmony_ci
3298141cc406Sopenharmony_ciSANE_Status
3299141cc406Sopenharmony_cisane_start (SANE_Handle handle)
3300141cc406Sopenharmony_ci{
3301141cc406Sopenharmony_ci  char *mode, *halftone, *gamma, *edge, *lightcolor, *adf_fsu;
3302141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
3303141cc406Sopenharmony_ci  SANE_Status status;
3304141cc406Sopenharmony_ci  size_t buf_size;
3305141cc406Sopenharmony_ci  SHARP_Send ss;
3306141cc406Sopenharmony_ci  window_param wp;
3307141cc406Sopenharmony_ci  mode_sense_subdevice m_subdev;
3308141cc406Sopenharmony_ci
3309141cc406Sopenharmony_ci  DBG (10, "<< sane_start ");
3310141cc406Sopenharmony_ci
3311141cc406Sopenharmony_ci  /* First make sure we have a current parameter set.  Some of the
3312141cc406Sopenharmony_ci     parameters will be overwritten below, but that's OK.  */
3313141cc406Sopenharmony_ci  status = sane_get_parameters (s, 0);
3314141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3315141cc406Sopenharmony_ci    return status;
3316141cc406Sopenharmony_ci
3317141cc406Sopenharmony_ci  s->dev->sensedat.complain_on_errors
3318141cc406Sopenharmony_ci    = COMPLAIN_ON_ADF_ERROR | s->dev->info.complain_on_errors;
3319141cc406Sopenharmony_ci
3320141cc406Sopenharmony_ci#ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
3321141cc406Sopenharmony_ci  s->dev->info.bufsize = s->dev->info.wanted_bufsize;
3322141cc406Sopenharmony_ci  if (s->dev->info.bufsize < 32 * 1024)
3323141cc406Sopenharmony_ci    s->dev->info.bufsize = 32 * 1024;
3324141cc406Sopenharmony_ci  {
3325141cc406Sopenharmony_ci    int bsize = s->dev->info.bufsize;
3326141cc406Sopenharmony_ci    status = sanei_scsi_open_extended (s->dev->sane.name, &s->fd,
3327141cc406Sopenharmony_ci              &sense_handler, &s->dev->sensedat, &bsize);
3328141cc406Sopenharmony_ci    s->dev->info.bufsize = bsize;
3329141cc406Sopenharmony_ci  }
3330141cc406Sopenharmony_ci
3331141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3332141cc406Sopenharmony_ci    {
3333141cc406Sopenharmony_ci      DBG (1, "open of %s failed: %s\n",
3334141cc406Sopenharmony_ci         s->dev->sane.name, sane_strstatus (status));
3335141cc406Sopenharmony_ci      return (status);
3336141cc406Sopenharmony_ci    }
3337141cc406Sopenharmony_ci
3338141cc406Sopenharmony_ci  /* make sure that we got at least 32 kB. Even then, the scan will be
3339141cc406Sopenharmony_ci     awfully slow.
3340141cc406Sopenharmony_ci
3341141cc406Sopenharmony_ci     NOTE: If you need to decrease this value, remember that s->buffer
3342141cc406Sopenharmony_ci     is used in send_ascii_gamma_tables (JX330/JX610) and in
3343141cc406Sopenharmony_ci     send_binary_g_table (JX250/JX350). send_ascii_gamma_tables needs 4106
3344141cc406Sopenharmony_ci     bytes, and send_binary_g_table needs 522 bytes.
3345141cc406Sopenharmony_ci  */
3346141cc406Sopenharmony_ci  if (s->dev->info.bufsize < 32 * 1024)
3347141cc406Sopenharmony_ci    {
3348141cc406Sopenharmony_ci      sanei_scsi_close(s->fd);
3349141cc406Sopenharmony_ci      s->fd = -1;
3350141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
3351141cc406Sopenharmony_ci    }
3352141cc406Sopenharmony_ci#else
3353141cc406Sopenharmony_ci  status = sanei_scsi_open(s->dev->sane.name, &s->fd, &sense_handler,
3354141cc406Sopenharmony_ci              &s->dev->sensedat);
3355141cc406Sopenharmony_ci  if (s->dev->info.wanted_bufsize < sanei_scsi_max_request_size)
3356141cc406Sopenharmony_ci    s->dev->info.bufsize = s->dev->info.wanted_bufsize;
3357141cc406Sopenharmony_ci  else
3358141cc406Sopenharmony_ci    s->dev->info.bufsize = sanei_scsi_max_request_size;
3359141cc406Sopenharmony_ci
3360141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3361141cc406Sopenharmony_ci    {
3362141cc406Sopenharmony_ci      DBG (1, "open of %s failed: %s\n",
3363141cc406Sopenharmony_ci         s->dev->sane.name, sane_strstatus (status));
3364141cc406Sopenharmony_ci      return (status);
3365141cc406Sopenharmony_ci    }
3366141cc406Sopenharmony_ci#endif
3367141cc406Sopenharmony_ci
3368141cc406Sopenharmony_ci  s->buffer = malloc(s->dev->info.bufsize);
3369141cc406Sopenharmony_ci  if (!s->buffer) {
3370141cc406Sopenharmony_ci    sanei_scsi_close(s->fd);
3371141cc406Sopenharmony_ci    s->fd = -1;
3372141cc406Sopenharmony_ci    free(s);
3373141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
3374141cc406Sopenharmony_ci  }
3375141cc406Sopenharmony_ci
3376141cc406Sopenharmony_ci#ifdef USE_FORK
3377141cc406Sopenharmony_ci  {
3378141cc406Sopenharmony_ci    struct shmid_ds ds;
3379141cc406Sopenharmony_ci    size_t n;
3380141cc406Sopenharmony_ci
3381141cc406Sopenharmony_ci    s->shmid = shmget(IPC_PRIVATE,
3382141cc406Sopenharmony_ci       sizeof(SHARP_rdr_ctl)
3383141cc406Sopenharmony_ci       + s->dev->info.buffers *
3384141cc406Sopenharmony_ci         (sizeof(SHARP_shmem_ctl) + s->dev->info.bufsize),
3385141cc406Sopenharmony_ci       IPC_CREAT | 0600);
3386141cc406Sopenharmony_ci    if (s->shmid == -1)
3387141cc406Sopenharmony_ci      {
3388141cc406Sopenharmony_ci        free(s->buffer);
3389141cc406Sopenharmony_ci        s->buffer = 0;
3390141cc406Sopenharmony_ci        sanei_scsi_close(s->fd);
3391141cc406Sopenharmony_ci        s->fd = -1;
3392141cc406Sopenharmony_ci        return SANE_STATUS_NO_MEM;
3393141cc406Sopenharmony_ci      }
3394141cc406Sopenharmony_ci    s->rdr_ctl = (SHARP_rdr_ctl*) shmat(s->shmid, 0, 0);
3395141cc406Sopenharmony_ci    if (s->rdr_ctl == (void *) -1)
3396141cc406Sopenharmony_ci     {
3397141cc406Sopenharmony_ci       shmctl(s->shmid, IPC_RMID, &ds);
3398141cc406Sopenharmony_ci       free(s->buffer);
3399141cc406Sopenharmony_ci       s->buffer = 0;
3400141cc406Sopenharmony_ci       sanei_scsi_close(s->fd);
3401141cc406Sopenharmony_ci       s->fd = -1;
3402141cc406Sopenharmony_ci       return SANE_STATUS_NO_MEM;
3403141cc406Sopenharmony_ci     }
3404141cc406Sopenharmony_ci
3405141cc406Sopenharmony_ci    s->rdr_ctl->buf_ctl = (SHARP_shmem_ctl*) &s->rdr_ctl[1];
3406141cc406Sopenharmony_ci    for (n = 0; n < s->dev->info.buffers; n++)
3407141cc406Sopenharmony_ci      {
3408141cc406Sopenharmony_ci        s->rdr_ctl->buf_ctl[n].buffer =
3409141cc406Sopenharmony_ci          (SANE_Byte*) &s->rdr_ctl->buf_ctl[s->dev->info.buffers]
3410141cc406Sopenharmony_ci            + n * s->dev->info.bufsize;
3411141cc406Sopenharmony_ci      }
3412141cc406Sopenharmony_ci  }
3413141cc406Sopenharmony_ci#endif /* USE_FORK */
3414141cc406Sopenharmony_ci
3415141cc406Sopenharmony_ci  DBG (5, "start: TEST_UNIT_READY\n");
3416141cc406Sopenharmony_ci  status = test_unit_ready (s->fd);
3417141cc406Sopenharmony_ci
3418141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3419141cc406Sopenharmony_ci    {
3420141cc406Sopenharmony_ci      DBG (1, "TEST UNIT READY failed: %s\n", sane_strstatus (status));
3421141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
3422141cc406Sopenharmony_ci      s->fd = -1;
3423141cc406Sopenharmony_ci      return (status);
3424141cc406Sopenharmony_ci    }
3425141cc406Sopenharmony_ci
3426141cc406Sopenharmony_ci  DBG (3, "start: sending MODE SELECT\n");
3427141cc406Sopenharmony_ci  status = mode_select_mud (s->fd, s->dev->info.mud);
3428141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3429141cc406Sopenharmony_ci    {
3430141cc406Sopenharmony_ci      DBG (1, "start: MODE_SELECT6 failed\n");
3431141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
3432141cc406Sopenharmony_ci      s->fd = -1;
3433141cc406Sopenharmony_ci      return (status);
3434141cc406Sopenharmony_ci    }
3435141cc406Sopenharmony_ci
3436141cc406Sopenharmony_ci  mode = s->val[OPT_MODE].s;
3437141cc406Sopenharmony_ci  halftone = s->val[OPT_HALFTONE].s;
3438141cc406Sopenharmony_ci  gamma = s->val[OPT_GAMMA].s;
3439141cc406Sopenharmony_ci  edge = s->val[OPT_EDGE_EMPHASIS].s;
3440141cc406Sopenharmony_ci  lightcolor = s->val[OPT_LIGHTCOLOR].s;
3441141cc406Sopenharmony_ci  adf_fsu = s->val[OPT_SCANSOURCE].s;
3442141cc406Sopenharmony_ci  s->speed = s->val[OPT_SPEED].w;
3443141cc406Sopenharmony_ci
3444141cc406Sopenharmony_ci  s->xres = s->val[OPT_X_RESOLUTION].w;
3445141cc406Sopenharmony_ci  if (s->val[OPT_PREVIEW].w == SANE_FALSE)
3446141cc406Sopenharmony_ci    {
3447141cc406Sopenharmony_ci#ifdef USE_SEPARATE_Y_RESOLUTION
3448141cc406Sopenharmony_ci      s->yres = s->val[OPT_Y_RESOLUTION].w;
3449141cc406Sopenharmony_ci#else
3450141cc406Sopenharmony_ci      s->yres = s->val[OPT_X_RESOLUTION].w;
3451141cc406Sopenharmony_ci#endif
3452141cc406Sopenharmony_ci      s->speed = s->val[OPT_SPEED].w;
3453141cc406Sopenharmony_ci    }
3454141cc406Sopenharmony_ci  else
3455141cc406Sopenharmony_ci    {
3456141cc406Sopenharmony_ci      s->yres = s->val[OPT_X_RESOLUTION].w;
3457141cc406Sopenharmony_ci      s->speed = SANE_TRUE;
3458141cc406Sopenharmony_ci    }
3459141cc406Sopenharmony_ci
3460141cc406Sopenharmony_ci  s->ulx = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud);
3461141cc406Sopenharmony_ci  s->uly = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud);
3462141cc406Sopenharmony_ci  s->threshold = s->val[OPT_THRESHOLD].w;
3463141cc406Sopenharmony_ci  s->bpp = s->params.depth;
3464141cc406Sopenharmony_ci
3465141cc406Sopenharmony_ci  s->adf_fsu_mode = SCAN_SIMPLE; /* default: scan without ADF and FSU */
3466141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
3467141cc406Sopenharmony_ci  if (strcmp (adf_fsu, use_auto) == 0)
3468141cc406Sopenharmony_ci    s->adf_fsu_mode = SCAN_ADF_FSU_AUTO;
3469141cc406Sopenharmony_ci  else
3470141cc406Sopenharmony_ci#endif
3471141cc406Sopenharmony_ci  if (strcmp(adf_fsu, use_fsu) == 0)
3472141cc406Sopenharmony_ci    s->adf_fsu_mode = SCAN_WITH_FSU;
3473141cc406Sopenharmony_ci  else if (strcmp(adf_fsu, use_adf) == 0)
3474141cc406Sopenharmony_ci    s->adf_fsu_mode = SCAN_WITH_ADF;
3475141cc406Sopenharmony_ci  else if (strcmp(adf_fsu, use_adf) == 0)
3476141cc406Sopenharmony_ci    s->adf_fsu_mode = SCAN_SIMPLE;
3477141cc406Sopenharmony_ci
3478141cc406Sopenharmony_ci  if (strcmp (mode, M_LINEART) == 0)
3479141cc406Sopenharmony_ci    {
3480141cc406Sopenharmony_ci      s->reverse = 0;
3481141cc406Sopenharmony_ci      if (strcmp(halftone, M_BILEVEL) == 0)
3482141cc406Sopenharmony_ci        {
3483141cc406Sopenharmony_ci          s->halftone = 1;
3484141cc406Sopenharmony_ci          s->image_composition = 0;
3485141cc406Sopenharmony_ci        }
3486141cc406Sopenharmony_ci      else if (strcmp(halftone, M_BAYER) == 0)
3487141cc406Sopenharmony_ci        {
3488141cc406Sopenharmony_ci          s->halftone = 2;
3489141cc406Sopenharmony_ci          s->image_composition = 1;
3490141cc406Sopenharmony_ci        }
3491141cc406Sopenharmony_ci      else if (strcmp(halftone, M_SPIRAL) == 0)
3492141cc406Sopenharmony_ci        {
3493141cc406Sopenharmony_ci          s->halftone = 3;
3494141cc406Sopenharmony_ci          s->image_composition = 1;
3495141cc406Sopenharmony_ci        }
3496141cc406Sopenharmony_ci      else if (strcmp(halftone, M_DISPERSED) == 0)
3497141cc406Sopenharmony_ci        {
3498141cc406Sopenharmony_ci          s->halftone = 4;
3499141cc406Sopenharmony_ci          s->image_composition = 1;
3500141cc406Sopenharmony_ci        }
3501141cc406Sopenharmony_ci      else if (strcmp(halftone, M_ERRDIFFUSION) == 0)
3502141cc406Sopenharmony_ci        {
3503141cc406Sopenharmony_ci          s->halftone = 5;
3504141cc406Sopenharmony_ci          s->image_composition = 1;
3505141cc406Sopenharmony_ci        }
3506141cc406Sopenharmony_ci    }
3507141cc406Sopenharmony_ci  else if (strcmp (mode, M_GRAY) == 0)
3508141cc406Sopenharmony_ci    {
3509141cc406Sopenharmony_ci      s->image_composition = 2;
3510141cc406Sopenharmony_ci      s->reverse = 1;
3511141cc406Sopenharmony_ci    }
3512141cc406Sopenharmony_ci  else if (strcmp (mode, M_LINEART_COLOR) == 0)
3513141cc406Sopenharmony_ci    {
3514141cc406Sopenharmony_ci      s->reverse = 1;
3515141cc406Sopenharmony_ci      if (strcmp(halftone, M_BILEVEL) == 0)
3516141cc406Sopenharmony_ci        {
3517141cc406Sopenharmony_ci          s->halftone = 1;
3518141cc406Sopenharmony_ci          s->image_composition = 3;
3519141cc406Sopenharmony_ci        }
3520141cc406Sopenharmony_ci      else if (strcmp(halftone, M_BAYER) == 0)
3521141cc406Sopenharmony_ci        {
3522141cc406Sopenharmony_ci          s->halftone = 2;
3523141cc406Sopenharmony_ci          s->image_composition = 4;
3524141cc406Sopenharmony_ci        }
3525141cc406Sopenharmony_ci      else if (strcmp(halftone, M_SPIRAL) == 0)
3526141cc406Sopenharmony_ci        {
3527141cc406Sopenharmony_ci          s->halftone = 3;
3528141cc406Sopenharmony_ci          s->image_composition = 4;
3529141cc406Sopenharmony_ci        }
3530141cc406Sopenharmony_ci      else if (strcmp(halftone, M_DISPERSED) == 0)
3531141cc406Sopenharmony_ci        {
3532141cc406Sopenharmony_ci          s->halftone = 4;
3533141cc406Sopenharmony_ci          s->image_composition = 4;
3534141cc406Sopenharmony_ci        }
3535141cc406Sopenharmony_ci      else if (strcmp(halftone, M_ERRDIFFUSION) == 0)
3536141cc406Sopenharmony_ci        {
3537141cc406Sopenharmony_ci          s->halftone = 5;
3538141cc406Sopenharmony_ci          s->image_composition = 4;
3539141cc406Sopenharmony_ci        }
3540141cc406Sopenharmony_ci    }
3541141cc406Sopenharmony_ci  else if (strcmp (mode, M_COLOR) == 0)
3542141cc406Sopenharmony_ci    {
3543141cc406Sopenharmony_ci      s->image_composition = 5;
3544141cc406Sopenharmony_ci      s->reverse = 1;
3545141cc406Sopenharmony_ci    }
3546141cc406Sopenharmony_ci
3547141cc406Sopenharmony_ci  if (strcmp (edge, EDGE_NONE) == 0)
3548141cc406Sopenharmony_ci    {
3549141cc406Sopenharmony_ci      DBG (11, "EDGE EMPHASIS NONE\n");
3550141cc406Sopenharmony_ci      s->edge = 0;
3551141cc406Sopenharmony_ci    }
3552141cc406Sopenharmony_ci  else if (strcmp (edge, EDGE_MIDDLE) == 0)
3553141cc406Sopenharmony_ci    {
3554141cc406Sopenharmony_ci      DBG (11, "EDGE EMPHASIS MIDDLE\n");
3555141cc406Sopenharmony_ci      s->edge = 1;
3556141cc406Sopenharmony_ci    }
3557141cc406Sopenharmony_ci  else if (strcmp (edge, EDGE_STRONG) == 0)
3558141cc406Sopenharmony_ci    {
3559141cc406Sopenharmony_ci      DBG (11, "EDGE EMPHASIS STRONG\n");
3560141cc406Sopenharmony_ci      s->edge = 2;
3561141cc406Sopenharmony_ci    }
3562141cc406Sopenharmony_ci  else if (strcmp (edge, EDGE_BLUR) == 0)
3563141cc406Sopenharmony_ci    {
3564141cc406Sopenharmony_ci      DBG (11, "EDGE EMPHASIS BLUR\n");
3565141cc406Sopenharmony_ci      s->edge = 3;
3566141cc406Sopenharmony_ci    }
3567141cc406Sopenharmony_ci
3568141cc406Sopenharmony_ci  s->lightcolor = 3;
3569141cc406Sopenharmony_ci  if (strcmp(lightcolor, LIGHT_GREEN) == 0)
3570141cc406Sopenharmony_ci    s->lightcolor = 0;
3571141cc406Sopenharmony_ci  else if (strcmp(lightcolor, LIGHT_RED) == 0)
3572141cc406Sopenharmony_ci    s->lightcolor = 1;
3573141cc406Sopenharmony_ci  else if (strcmp(lightcolor, LIGHT_BLUE) == 0)
3574141cc406Sopenharmony_ci    s->lightcolor = 2;
3575141cc406Sopenharmony_ci  else if (strcmp(lightcolor, LIGHT_WHITE) == 0)
3576141cc406Sopenharmony_ci    s->lightcolor = 3;
3577141cc406Sopenharmony_ci
3578141cc406Sopenharmony_ci  s->adf_scan = 0;
3579141cc406Sopenharmony_ci  if (   s->dev->sensedat.model != JX610
3580141cc406Sopenharmony_ci      && s->dev->sensedat.model != JX320)
3581141cc406Sopenharmony_ci    {
3582141cc406Sopenharmony_ci      status = mode_select_adf_fsu(s->fd, s->adf_fsu_mode);
3583141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3584141cc406Sopenharmony_ci        {
3585141cc406Sopenharmony_ci          DBG (10, "sane_start: mode_select_adf_fsu failed: %s\n", sane_strstatus (status));
3586141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3587141cc406Sopenharmony_ci          s->fd = -1;
3588141cc406Sopenharmony_ci          return (status);
3589141cc406Sopenharmony_ci        }
3590141cc406Sopenharmony_ci      /* if the ADF is selected, check if it is ready */
3591141cc406Sopenharmony_ci      memset (&m_subdev, 0, sizeof (m_subdev));
3592141cc406Sopenharmony_ci      buf_size = sizeof (m_subdev);
3593141cc406Sopenharmony_ci      status = mode_sense (s->fd, &m_subdev, &buf_size, 0x20);
3594141cc406Sopenharmony_ci      DBG(11, "mode sense result a_mode: %x f_mode: %x\n",
3595141cc406Sopenharmony_ci          m_subdev.a_mode_type, m_subdev.f_mode_type);
3596141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3597141cc406Sopenharmony_ci        {
3598141cc406Sopenharmony_ci          DBG (10, "sane_start: MODE_SENSE/subdevice page failed\n");
3599141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3600141cc406Sopenharmony_ci          s->fd = -1;
3601141cc406Sopenharmony_ci          return (status);
3602141cc406Sopenharmony_ci        }
3603141cc406Sopenharmony_ci      if (s->adf_fsu_mode == SCAN_WITH_ADF)
3604141cc406Sopenharmony_ci        s->adf_scan = 1;
3605141cc406Sopenharmony_ci#ifdef ALLOW_AUTO_SELECT_ADF
3606141cc406Sopenharmony_ci      else if (s->adf_fsu_mode == SCAN_ADF_FSU_AUTO)
3607141cc406Sopenharmony_ci        {
3608141cc406Sopenharmony_ci          if (m_subdev.a_mode_type & 0x80)
3609141cc406Sopenharmony_ci            s->adf_scan = 1;
3610141cc406Sopenharmony_ci        }
3611141cc406Sopenharmony_ci#endif
3612141cc406Sopenharmony_ci    }
3613141cc406Sopenharmony_ci
3614141cc406Sopenharmony_ci
3615141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
3616141cc406Sopenharmony_ci  if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE)
3617141cc406Sopenharmony_ci    {
3618141cc406Sopenharmony_ci#endif
3619141cc406Sopenharmony_ci      if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350)
3620141cc406Sopenharmony_ci        {
3621141cc406Sopenharmony_ci          ss.dtc = 0x03;
3622141cc406Sopenharmony_ci          if (strcmp (gamma, GAMMA10) == 0)
3623141cc406Sopenharmony_ci          {
3624141cc406Sopenharmony_ci              ss.dtq = 0x01;
3625141cc406Sopenharmony_ci          }else{
3626141cc406Sopenharmony_ci              ss.dtq = 0x02;
3627141cc406Sopenharmony_ci          }
3628141cc406Sopenharmony_ci          ss.length = 0;
3629141cc406Sopenharmony_ci          DBG (5, "start: SEND\n");
3630141cc406Sopenharmony_ci          status = send (s->fd,  &ss);
3631141cc406Sopenharmony_ci          if (status != SANE_STATUS_GOOD)
3632141cc406Sopenharmony_ci            {
3633141cc406Sopenharmony_ci              DBG (1, "send failed: %s\n", sane_strstatus (status));
3634141cc406Sopenharmony_ci              sanei_scsi_close (s->fd);
3635141cc406Sopenharmony_ci              s->fd = -1;
3636141cc406Sopenharmony_ci              return (status);
3637141cc406Sopenharmony_ci            }
3638141cc406Sopenharmony_ci       }
3639141cc406Sopenharmony_ci     else
3640141cc406Sopenharmony_ci       {
3641141cc406Sopenharmony_ci         /* the JX250 does not support the "fixed gamma selection",
3642141cc406Sopenharmony_ci            therefore, lets calculate & send gamma values
3643141cc406Sopenharmony_ci         */
3644141cc406Sopenharmony_ci         int i;
3645141cc406Sopenharmony_ci         SANE_Word gtbl[256];
3646141cc406Sopenharmony_ci         if (strcmp (gamma, GAMMA10) == 0)
3647141cc406Sopenharmony_ci           for (i = 0; i < 256; i++)
3648141cc406Sopenharmony_ci             gtbl[i] = i;
3649141cc406Sopenharmony_ci         else
3650141cc406Sopenharmony_ci           {
3651141cc406Sopenharmony_ci             gtbl[0] = 0;
3652141cc406Sopenharmony_ci             for (i = 1; i < 256; i++)
3653141cc406Sopenharmony_ci               gtbl[i] = 255 * exp(0.45 * log(i/255.0));
3654141cc406Sopenharmony_ci           }
3655141cc406Sopenharmony_ci         send_binary_g_table(s, gtbl, 0x10);
3656141cc406Sopenharmony_ci         send_binary_g_table(s, gtbl, 0x11);
3657141cc406Sopenharmony_ci         send_binary_g_table(s, gtbl, 0x12);
3658141cc406Sopenharmony_ci         send_binary_g_table(s, gtbl, 0x13);
3659141cc406Sopenharmony_ci       }
3660141cc406Sopenharmony_ci#ifdef USE_CUSTOM_GAMMA
3661141cc406Sopenharmony_ci    }
3662141cc406Sopenharmony_ci  else
3663141cc406Sopenharmony_ci    status = send_gamma_tables(s);
3664141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3665141cc406Sopenharmony_ci        {
3666141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3667141cc406Sopenharmony_ci          s->fd = -1;
3668141cc406Sopenharmony_ci          return (status);
3669141cc406Sopenharmony_ci        }
3670141cc406Sopenharmony_ci#endif
3671141cc406Sopenharmony_ci
3672141cc406Sopenharmony_ci  if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350)
3673141cc406Sopenharmony_ci    {
3674141cc406Sopenharmony_ci      ss.dtc = 0x86;
3675141cc406Sopenharmony_ci      ss.dtq = 0x05;
3676141cc406Sopenharmony_ci      ss.length = 0;
3677141cc406Sopenharmony_ci      DBG (5, "start: SEND\n");
3678141cc406Sopenharmony_ci      status = send (s->fd,  &ss);
3679141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3680141cc406Sopenharmony_ci        {
3681141cc406Sopenharmony_ci          DBG (1, "send failed: %s\n", sane_strstatus (status));
3682141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3683141cc406Sopenharmony_ci          s->fd = -1;
3684141cc406Sopenharmony_ci          return (status);
3685141cc406Sopenharmony_ci        }
3686141cc406Sopenharmony_ci
3687141cc406Sopenharmony_ci#ifdef USE_COLOR_THRESHOLD
3688141cc406Sopenharmony_ci      status = send_threshold_data(s);
3689141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3690141cc406Sopenharmony_ci        {
3691141cc406Sopenharmony_ci          DBG (1, "send threshold data failed: %s\n", sane_strstatus (status));
3692141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3693141cc406Sopenharmony_ci          s->fd = -1;
3694141cc406Sopenharmony_ci          return (status);
3695141cc406Sopenharmony_ci        }
3696141cc406Sopenharmony_ci#endif
3697141cc406Sopenharmony_ci    }
3698141cc406Sopenharmony_ci
3699141cc406Sopenharmony_ci  memset (&wp, 0, sizeof (wp));
3700141cc406Sopenharmony_ci  /* every Sharp scanner seems to have a different
3701141cc406Sopenharmony_ci     window descriptor block...
3702141cc406Sopenharmony_ci  */
3703141cc406Sopenharmony_ci  if (   s->dev->sensedat.model == JX610
3704141cc406Sopenharmony_ci      || s->dev->sensedat.model == JX320)
3705141cc406Sopenharmony_ci    {
3706141cc406Sopenharmony_ci      buf_size = sizeof(WDB);
3707141cc406Sopenharmony_ci    }
3708141cc406Sopenharmony_ci  else if (s->dev->sensedat.model == JX330)
3709141cc406Sopenharmony_ci    {
3710141cc406Sopenharmony_ci      buf_size = sizeof (WDB) + sizeof(WDBX330);
3711141cc406Sopenharmony_ci    }
3712141cc406Sopenharmony_ci  else
3713141cc406Sopenharmony_ci    {
3714141cc406Sopenharmony_ci      buf_size = sizeof (WDB) + sizeof(WDBX330) + sizeof(WDBX250);
3715141cc406Sopenharmony_ci    }
3716141cc406Sopenharmony_ci
3717141cc406Sopenharmony_ci  wp.wpdh.wdl[0] = buf_size >> 8;
3718141cc406Sopenharmony_ci  wp.wpdh.wdl[1] = buf_size;
3719141cc406Sopenharmony_ci  wp.wdb.x_res[0] = s->xres >> 8;
3720141cc406Sopenharmony_ci  wp.wdb.x_res[1] = s->xres;
3721141cc406Sopenharmony_ci  wp.wdb.y_res[0] = s->yres >> 8;
3722141cc406Sopenharmony_ci  wp.wdb.y_res[1] = s->yres;
3723141cc406Sopenharmony_ci  wp.wdb.x_ul[0] = s->ulx >> 24;
3724141cc406Sopenharmony_ci  wp.wdb.x_ul[1] = s->ulx >> 16;
3725141cc406Sopenharmony_ci  wp.wdb.x_ul[2] = s->ulx >> 8;
3726141cc406Sopenharmony_ci  wp.wdb.x_ul[3] = s->ulx;
3727141cc406Sopenharmony_ci  wp.wdb.y_ul[0] = s->uly >> 24;
3728141cc406Sopenharmony_ci  wp.wdb.y_ul[1] = s->uly >> 16;
3729141cc406Sopenharmony_ci  wp.wdb.y_ul[2] = s->uly >> 8;
3730141cc406Sopenharmony_ci  wp.wdb.y_ul[3] = s->uly;
3731141cc406Sopenharmony_ci  wp.wdb.width[0] = s->width >> 24;
3732141cc406Sopenharmony_ci  wp.wdb.width[1] = s->width >> 16;
3733141cc406Sopenharmony_ci  wp.wdb.width[2] = s->width >> 8;
3734141cc406Sopenharmony_ci  wp.wdb.width[3] = s->width;
3735141cc406Sopenharmony_ci  wp.wdb.length[0] = s->length >> 24;
3736141cc406Sopenharmony_ci  wp.wdb.length[1] = s->length >> 16;
3737141cc406Sopenharmony_ci  wp.wdb.length[2] = s->length >> 8;
3738141cc406Sopenharmony_ci  wp.wdb.length[3] = s->length;
3739141cc406Sopenharmony_ci  wp.wdb.brightness = 0;
3740141cc406Sopenharmony_ci  wp.wdb.threshold = s->threshold;
3741141cc406Sopenharmony_ci  wp.wdb.image_composition = s->image_composition;
3742141cc406Sopenharmony_ci  if (s->image_composition <= 2 || s->image_composition >= 5)
3743141cc406Sopenharmony_ci    wp.wdb.bpp = s->bpp;
3744141cc406Sopenharmony_ci  else
3745141cc406Sopenharmony_ci    wp.wdb.bpp = 1;
3746141cc406Sopenharmony_ci  wp.wdb.ht_pattern[0] = 0;
3747141cc406Sopenharmony_ci  if (   s->dev->sensedat.model == JX610
3748141cc406Sopenharmony_ci      || s->dev->sensedat.model == JX320)
3749141cc406Sopenharmony_ci    {
3750141cc406Sopenharmony_ci      wp.wdb.ht_pattern[1] = 0;
3751141cc406Sopenharmony_ci    }else{
3752141cc406Sopenharmony_ci      wp.wdb.ht_pattern[1] = s->halftone;
3753141cc406Sopenharmony_ci    }
3754141cc406Sopenharmony_ci  wp.wdb.rif_padding = (s->reverse * 128) + 0;
3755141cc406Sopenharmony_ci  wp.wdb.eletu = (!s->speed << 2) + (s->edge << 6) + (s->lightcolor << 4);
3756141cc406Sopenharmony_ci
3757141cc406Sopenharmony_ci  if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350)
3758141cc406Sopenharmony_ci    {
3759141cc406Sopenharmony_ci      wp.wdbx250.threshold_red   = s->val[OPT_THRESHOLD_R].w;
3760141cc406Sopenharmony_ci      wp.wdbx250.threshold_green = s->val[OPT_THRESHOLD_G].w;
3761141cc406Sopenharmony_ci      wp.wdbx250.threshold_blue  = s->val[OPT_THRESHOLD_B].w;
3762141cc406Sopenharmony_ci    }
3763141cc406Sopenharmony_ci
3764141cc406Sopenharmony_ci
3765141cc406Sopenharmony_ci  DBG (5, "wdl=%d\n", (wp.wpdh.wdl[0] << 8) + wp.wpdh.wdl[1]);
3766141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]);
3767141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]);
3768141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) +
3769141cc406Sopenharmony_ci                      (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]);
3770141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) +
3771141cc406Sopenharmony_ci                      (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]);
3772141cc406Sopenharmony_ci  DBG (5, "width=%d\n", (wp.wdb.width[0] << 8) + (wp.wdb.width[1] << 16) +
3773141cc406Sopenharmony_ci                        (wp.wdb.width[2] << 8) + wp.wdb.width[3]);
3774141cc406Sopenharmony_ci  DBG (5, "length=%d\n", (wp.wdb.length[0] << 16) + (wp.wdb.length[1] << 16) +
3775141cc406Sopenharmony_ci                         (wp.wdb.length[2] << 8) + wp.wdb.length[3]);
3776141cc406Sopenharmony_ci
3777141cc406Sopenharmony_ci  DBG (5, "threshold=%d\n", wp.wdb.threshold);
3778141cc406Sopenharmony_ci  DBG (5, "image_composition=%d\n", wp.wdb.image_composition);
3779141cc406Sopenharmony_ci  DBG (5, "bpp=%d\n", wp.wdb.bpp);
3780141cc406Sopenharmony_ci  DBG (5, "rif_padding=%d\n", wp.wdb.rif_padding);
3781141cc406Sopenharmony_ci  DBG (5, "eletu=%d\n", wp.wdb.eletu);
3782141cc406Sopenharmony_ci
3783141cc406Sopenharmony_ci#if 0
3784141cc406Sopenharmony_ci  {
3785141cc406Sopenharmony_ci    unsigned char *p = (unsigned char*) &wp.wdb;
3786141cc406Sopenharmony_ci    int i;
3787141cc406Sopenharmony_ci    DBG(11, "set window:\n");
3788141cc406Sopenharmony_ci    for (i = 0; i < sizeof(wp.wdb) + + sizeof(wp.wdbx330) + sizeof(wp.wdbx250); i += 16)
3789141cc406Sopenharmony_ci     {
3790141cc406Sopenharmony_ci      DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n",
3791141cc406Sopenharmony_ci      p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8],
3792141cc406Sopenharmony_ci      p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]);
3793141cc406Sopenharmony_ci     }
3794141cc406Sopenharmony_ci  }
3795141cc406Sopenharmony_ci#endif
3796141cc406Sopenharmony_ci
3797141cc406Sopenharmony_ci  buf_size += sizeof(WPDH);
3798141cc406Sopenharmony_ci  DBG (5, "start: SET WINDOW\n");
3799141cc406Sopenharmony_ci  status = set_window (s->fd, &wp, buf_size);
3800141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3801141cc406Sopenharmony_ci    {
3802141cc406Sopenharmony_ci      DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status));
3803141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
3804141cc406Sopenharmony_ci      s->fd = -1;
3805141cc406Sopenharmony_ci      return (status);
3806141cc406Sopenharmony_ci    }
3807141cc406Sopenharmony_ci
3808141cc406Sopenharmony_ci  memset (&wp, 0, buf_size);
3809141cc406Sopenharmony_ci  DBG (5, "start: GET WINDOW\n");
3810141cc406Sopenharmony_ci  status = get_window (s->fd, &wp, &buf_size);
3811141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3812141cc406Sopenharmony_ci    {
3813141cc406Sopenharmony_ci      DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status));
3814141cc406Sopenharmony_ci      sanei_scsi_close (s->fd);
3815141cc406Sopenharmony_ci      s->fd = -1;
3816141cc406Sopenharmony_ci      return (status);
3817141cc406Sopenharmony_ci    }
3818141cc406Sopenharmony_ci  DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]);
3819141cc406Sopenharmony_ci  DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]);
3820141cc406Sopenharmony_ci  DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) +
3821141cc406Sopenharmony_ci                      (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]);
3822141cc406Sopenharmony_ci  DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) +
3823141cc406Sopenharmony_ci       (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]);
3824141cc406Sopenharmony_ci  DBG (5, "width=%d\n", (wp.wdb.width[0] << 24) + (wp.wdb.width[1] << 16) +
3825141cc406Sopenharmony_ci                        (wp.wdb.width[2] << 8) + wp.wdb.width[3]);
3826141cc406Sopenharmony_ci  DBG (5, "length=%d\n", (wp.wdb.length[0] << 24) + (wp.wdb.length[1] << 16) +
3827141cc406Sopenharmony_ci                         (wp.wdb.length[2] << 8) + wp.wdb.length[3]);
3828141cc406Sopenharmony_ci
3829141cc406Sopenharmony_ci  if (s->adf_scan)
3830141cc406Sopenharmony_ci    {
3831141cc406Sopenharmony_ci      status = object_position(s->fd, LOAD_PAPER);
3832141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
3833141cc406Sopenharmony_ci        {
3834141cc406Sopenharmony_ci          sanei_scsi_close (s->fd);
3835141cc406Sopenharmony_ci          s->fd = -1;
3836141cc406Sopenharmony_ci          s->busy = SANE_FALSE;
3837141cc406Sopenharmony_ci          s->cancel = SANE_FALSE;
3838141cc406Sopenharmony_ci          return (status);
3839141cc406Sopenharmony_ci        }
3840141cc406Sopenharmony_ci    }
3841141cc406Sopenharmony_ci
3842141cc406Sopenharmony_ci  DBG (5, "start: SCAN\n");
3843141cc406Sopenharmony_ci  s->scanning = SANE_TRUE;
3844141cc406Sopenharmony_ci  s->busy = SANE_TRUE;
3845141cc406Sopenharmony_ci  s->cancel = SANE_FALSE;
3846141cc406Sopenharmony_ci  s->get_params_called = 0;
3847141cc406Sopenharmony_ci
3848141cc406Sopenharmony_ci  wait_ready(s->fd);
3849141cc406Sopenharmony_ci  status = scan (s->fd);
3850141cc406Sopenharmony_ci#ifdef DEBUG
3851141cc406Sopenharmony_ci          {
3852141cc406Sopenharmony_ci            struct timeval t;
3853141cc406Sopenharmony_ci            gettimeofday(&t, 0);
3854141cc406Sopenharmony_ci            DBG(2, "rd: scan started        %li.%06li\n", t.tv_sec, t.tv_usec);
3855141cc406Sopenharmony_ci          }
3856141cc406Sopenharmony_ci#endif
3857141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3858141cc406Sopenharmony_ci    {
3859141cc406Sopenharmony_ci      DBG (1, "start of scan failed: %s\n", sane_strstatus (status));
3860141cc406Sopenharmony_ci      do_cancel(s);
3861141cc406Sopenharmony_ci      return (status);
3862141cc406Sopenharmony_ci    }
3863141cc406Sopenharmony_ci
3864141cc406Sopenharmony_ci  /* ask the scanner for the scan size */
3865141cc406Sopenharmony_ci  /* wait_ready(s->fd); */
3866141cc406Sopenharmony_ci#ifdef DEBUG
3867141cc406Sopenharmony_ci          {
3868141cc406Sopenharmony_ci            struct timeval t;
3869141cc406Sopenharmony_ci            gettimeofday(&t, 0);
3870141cc406Sopenharmony_ci            DBG(2, "rd: wait_ready ok       %li.%06li\n", t.tv_sec, t.tv_usec);
3871141cc406Sopenharmony_ci          }
3872141cc406Sopenharmony_ci#endif
3873141cc406Sopenharmony_ci  sane_get_parameters(s, 0);
3874141cc406Sopenharmony_ci#ifdef DEBUG
3875141cc406Sopenharmony_ci          {
3876141cc406Sopenharmony_ci            struct timeval t;
3877141cc406Sopenharmony_ci            gettimeofday(&t, 0);
3878141cc406Sopenharmony_ci            DBG(2, "rd: get_params ok       %li.%06li\n", t.tv_sec, t.tv_usec);
3879141cc406Sopenharmony_ci          }
3880141cc406Sopenharmony_ci#endif
3881141cc406Sopenharmony_ci  if (strcmp (mode, M_LINEART_COLOR) != 0)
3882141cc406Sopenharmony_ci    s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
3883141cc406Sopenharmony_ci  else
3884141cc406Sopenharmony_ci    {
3885141cc406Sopenharmony_ci      s->bytes_to_read = (s->params.pixels_per_line+7) / 8;
3886141cc406Sopenharmony_ci      s->bytes_to_read *= 3 * s->params.lines;
3887141cc406Sopenharmony_ci    }
3888141cc406Sopenharmony_ci
3889141cc406Sopenharmony_ci#ifdef USE_FORK
3890141cc406Sopenharmony_ci  {
3891141cc406Sopenharmony_ci    size_t i;
3892141cc406Sopenharmony_ci    for (i = 0; i < s->dev->info.buffers; i++)
3893141cc406Sopenharmony_ci      s->rdr_ctl->buf_ctl[i].shm_status = SHM_EMPTY;
3894141cc406Sopenharmony_ci    s->read_buff = 0;
3895141cc406Sopenharmony_ci    s->rdr_ctl->cancel = 0;
3896141cc406Sopenharmony_ci    s->rdr_ctl->running = 0;
3897141cc406Sopenharmony_ci    s->rdr_ctl->status  = SANE_STATUS_GOOD;
3898141cc406Sopenharmony_ci  }
3899141cc406Sopenharmony_ci  s->reader_pid = fork();
3900141cc406Sopenharmony_ci#ifdef DEBUG
3901141cc406Sopenharmony_ci          {
3902141cc406Sopenharmony_ci            struct timeval t;
3903141cc406Sopenharmony_ci            gettimeofday(&t, 0);
3904141cc406Sopenharmony_ci            DBG(2, "rd: forked              %li.%06li %i\n", t.tv_sec, t.tv_usec,
3905141cc406Sopenharmony_ci              s->reader_pid);
3906141cc406Sopenharmony_ci          }
3907141cc406Sopenharmony_ci#endif
3908141cc406Sopenharmony_ci  if (s->reader_pid == 0)
3909141cc406Sopenharmony_ci    {
3910141cc406Sopenharmony_ci      sigset_t ignore_set;
3911141cc406Sopenharmony_ci      struct SIGACTION act;
3912141cc406Sopenharmony_ci
3913141cc406Sopenharmony_ci      sigfillset (&ignore_set);
3914141cc406Sopenharmony_ci      sigdelset (&ignore_set, SIGTERM);
3915141cc406Sopenharmony_ci      sigprocmask (SIG_SETMASK, &ignore_set, 0);
3916141cc406Sopenharmony_ci
3917141cc406Sopenharmony_ci      memset (&act, 0, sizeof (act));
3918141cc406Sopenharmony_ci      sigaction (SIGTERM, &act, 0);
3919141cc406Sopenharmony_ci
3920141cc406Sopenharmony_ci      /* don't use exit() since that would run the atexit() handlers... */
3921141cc406Sopenharmony_ci      _exit (reader_process (s));
3922141cc406Sopenharmony_ci    }
3923141cc406Sopenharmony_ci  else if (s->reader_pid == -1)
3924141cc406Sopenharmony_ci    {
3925141cc406Sopenharmony_ci      s->busy = SANE_FALSE;
3926141cc406Sopenharmony_ci      do_cancel(s);
3927141cc406Sopenharmony_ci      return SANE_STATUS_NO_MEM;
3928141cc406Sopenharmony_ci    }
3929141cc406Sopenharmony_ci
3930141cc406Sopenharmony_ci#endif /* USE_FORK */
3931141cc406Sopenharmony_ci
3932141cc406Sopenharmony_ci
3933141cc406Sopenharmony_ci  DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, "
3934141cc406Sopenharmony_ci       "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line,
3935141cc406Sopenharmony_ci       s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_X_RESOLUTION].w);
3936141cc406Sopenharmony_ci
3937141cc406Sopenharmony_ci  s->busy = SANE_FALSE;
3938141cc406Sopenharmony_ci  s->buf_used = 0;
3939141cc406Sopenharmony_ci  s->buf_pos = 0;
3940141cc406Sopenharmony_ci
3941141cc406Sopenharmony_ci  if (s->cancel == SANE_TRUE)
3942141cc406Sopenharmony_ci    {
3943141cc406Sopenharmony_ci      do_cancel(s);
3944141cc406Sopenharmony_ci      DBG (10, ">>\n");
3945141cc406Sopenharmony_ci      return(SANE_STATUS_CANCELLED);
3946141cc406Sopenharmony_ci    }
3947141cc406Sopenharmony_ci
3948141cc406Sopenharmony_ci  DBG (10, ">>\n");
3949141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
3950141cc406Sopenharmony_ci
3951141cc406Sopenharmony_ci}
3952141cc406Sopenharmony_ci
3953141cc406Sopenharmony_cistatic SANE_Status
3954141cc406Sopenharmony_cisane_read_direct (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len,
3955141cc406Sopenharmony_ci	   SANE_Int * len)
3956141cc406Sopenharmony_ci{
3957141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
3958141cc406Sopenharmony_ci  SANE_Status status;
3959141cc406Sopenharmony_ci  size_t nread;
3960141cc406Sopenharmony_ci  DBG (10, "<< sane_read_direct ");
3961141cc406Sopenharmony_ci
3962141cc406Sopenharmony_ci  DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read);
3963141cc406Sopenharmony_ci  *len = 0;
3964141cc406Sopenharmony_ci
3965141cc406Sopenharmony_ci  if (s->bytes_to_read == 0)
3966141cc406Sopenharmony_ci    {
3967141cc406Sopenharmony_ci      do_cancel (s);
3968141cc406Sopenharmony_ci      return (SANE_STATUS_EOF);
3969141cc406Sopenharmony_ci    }
3970141cc406Sopenharmony_ci
3971141cc406Sopenharmony_ci  if (!s->scanning)
3972141cc406Sopenharmony_ci    return (do_cancel (s));
3973141cc406Sopenharmony_ci  nread = max_len;
3974141cc406Sopenharmony_ci  if (nread > s->bytes_to_read)
3975141cc406Sopenharmony_ci    nread = s->bytes_to_read;
3976141cc406Sopenharmony_ci  if (nread > s->dev->info.bufsize)
3977141cc406Sopenharmony_ci    nread = s->dev->info.bufsize;
3978141cc406Sopenharmony_ci#ifdef USE_FORK
3979141cc406Sopenharmony_ci  status = read_data(s, dst_buf, &nread);
3980141cc406Sopenharmony_ci#else
3981141cc406Sopenharmony_ci  wait_ready(s->fd);
3982141cc406Sopenharmony_ci  status = read_data (s, dst_buf, &nread);
3983141cc406Sopenharmony_ci#endif
3984141cc406Sopenharmony_ci  if (status != SANE_STATUS_GOOD)
3985141cc406Sopenharmony_ci    {
3986141cc406Sopenharmony_ci      do_cancel (s);
3987141cc406Sopenharmony_ci      return (SANE_STATUS_IO_ERROR);
3988141cc406Sopenharmony_ci    }
3989141cc406Sopenharmony_ci  *len = nread;
3990141cc406Sopenharmony_ci  s->bytes_to_read -= nread;
3991141cc406Sopenharmony_ci  DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read);
3992141cc406Sopenharmony_ci
3993141cc406Sopenharmony_ci  DBG (10, ">>\n");
3994141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
3995141cc406Sopenharmony_ci}
3996141cc406Sopenharmony_ci
3997141cc406Sopenharmony_cistatic SANE_Status
3998141cc406Sopenharmony_cisane_read_shuffled (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len,
3999141cc406Sopenharmony_ci	   SANE_Int * len, int eight_bit_data)
4000141cc406Sopenharmony_ci{
4001141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
4002141cc406Sopenharmony_ci  SANE_Status status;
4003141cc406Sopenharmony_ci  SANE_Byte *dest, *red, *green, *blue, mask;
4004141cc406Sopenharmony_ci  SANE_Int transfer;
4005141cc406Sopenharmony_ci  size_t nread, ntest, pixel, max_pixel, line, max_line;
4006141cc406Sopenharmony_ci  size_t start_input, bytes_per_line_in;
4007141cc406Sopenharmony_ci  DBG (10, "<< sane_read_shuffled ");
4008141cc406Sopenharmony_ci
4009141cc406Sopenharmony_ci  *len = 0;
4010141cc406Sopenharmony_ci  if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used)
4011141cc406Sopenharmony_ci    {
4012141cc406Sopenharmony_ci      do_cancel (s);
4013141cc406Sopenharmony_ci      DBG (10, ">>\n");
4014141cc406Sopenharmony_ci      return (SANE_STATUS_EOF);
4015141cc406Sopenharmony_ci    }
4016141cc406Sopenharmony_ci
4017141cc406Sopenharmony_ci  if (!s->scanning)
4018141cc406Sopenharmony_ci    {
4019141cc406Sopenharmony_ci      DBG (10, ">>\n");
4020141cc406Sopenharmony_ci      return(do_cancel(s));
4021141cc406Sopenharmony_ci    }
4022141cc406Sopenharmony_ci
4023141cc406Sopenharmony_ci  if (s->buf_pos < s->buf_used)
4024141cc406Sopenharmony_ci    {
4025141cc406Sopenharmony_ci      transfer = s->buf_used - s->buf_pos;
4026141cc406Sopenharmony_ci      if (transfer > max_len)
4027141cc406Sopenharmony_ci        transfer = max_len;
4028141cc406Sopenharmony_ci
4029141cc406Sopenharmony_ci      memcpy(dst_buf, &(s->buffer[s->buf_pos]), transfer);
4030141cc406Sopenharmony_ci      s->buf_pos += transfer;
4031141cc406Sopenharmony_ci      max_len -= transfer;
4032141cc406Sopenharmony_ci      *len = transfer;
4033141cc406Sopenharmony_ci    }
4034141cc406Sopenharmony_ci
4035141cc406Sopenharmony_ci  while (max_len > 0 && s->bytes_to_read > 0)
4036141cc406Sopenharmony_ci    {
4037141cc406Sopenharmony_ci      if (eight_bit_data)
4038141cc406Sopenharmony_ci        {
4039141cc406Sopenharmony_ci          nread = s->dev->info.bufsize / s->params.bytes_per_line - 1;
4040141cc406Sopenharmony_ci          nread *= s->params.bytes_per_line;
4041141cc406Sopenharmony_ci          if (nread > s->bytes_to_read)
4042141cc406Sopenharmony_ci            nread = s->bytes_to_read;
4043141cc406Sopenharmony_ci          max_line = nread / s->params.bytes_per_line;
4044141cc406Sopenharmony_ci          start_input = s->params.bytes_per_line;
4045141cc406Sopenharmony_ci          bytes_per_line_in = s->params.bytes_per_line;
4046141cc406Sopenharmony_ci        }
4047141cc406Sopenharmony_ci      else
4048141cc406Sopenharmony_ci        {
4049141cc406Sopenharmony_ci          bytes_per_line_in = (s->params.pixels_per_line + 7) / 8;
4050141cc406Sopenharmony_ci          bytes_per_line_in *= 3;
4051141cc406Sopenharmony_ci          max_line = s->params.bytes_per_line + bytes_per_line_in;
4052141cc406Sopenharmony_ci          max_line = s->dev->info.bufsize / max_line;
4053141cc406Sopenharmony_ci          nread = max_line * bytes_per_line_in;
4054141cc406Sopenharmony_ci          if (nread > s->bytes_to_read)
4055141cc406Sopenharmony_ci            {
4056141cc406Sopenharmony_ci              nread = s->bytes_to_read;
4057141cc406Sopenharmony_ci              max_line = nread / bytes_per_line_in;
4058141cc406Sopenharmony_ci            }
4059141cc406Sopenharmony_ci          start_input = s->dev->info.bufsize - nread;
4060141cc406Sopenharmony_ci        }
4061141cc406Sopenharmony_ci      ntest = nread;
4062141cc406Sopenharmony_ci
4063141cc406Sopenharmony_ci#ifdef USE_FORK
4064141cc406Sopenharmony_ci      status = read_data (s, &(s->buffer[start_input]), &nread);
4065141cc406Sopenharmony_ci#else
4066141cc406Sopenharmony_ci      wait_ready(s->fd);
4067141cc406Sopenharmony_ci      status = read_data (s, &(s->buffer[start_input]), &nread);
4068141cc406Sopenharmony_ci#endif
4069141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
4070141cc406Sopenharmony_ci        {
4071141cc406Sopenharmony_ci          do_cancel (s);
4072141cc406Sopenharmony_ci          DBG (10, ">>\n");
4073141cc406Sopenharmony_ci          return (SANE_STATUS_IO_ERROR);
4074141cc406Sopenharmony_ci        }
4075141cc406Sopenharmony_ci
4076141cc406Sopenharmony_ci      if (nread != ntest)
4077141cc406Sopenharmony_ci        {
4078141cc406Sopenharmony_ci          /* if this happens, something is wrong in the input buffer
4079141cc406Sopenharmony_ci             management...
4080141cc406Sopenharmony_ci          */
4081141cc406Sopenharmony_ci          DBG(1, "Warning: could not read an integral number of scan lines\n");
4082141cc406Sopenharmony_ci          DBG(1, "         image will be scrambled\n");
4083141cc406Sopenharmony_ci        }
4084141cc406Sopenharmony_ci
4085141cc406Sopenharmony_ci
4086141cc406Sopenharmony_ci      s->buf_used = max_line * s->params.bytes_per_line;
4087141cc406Sopenharmony_ci      s->buf_pos = 0;
4088141cc406Sopenharmony_ci      s->bytes_to_read -= nread;
4089141cc406Sopenharmony_ci      dest = s->buffer;
4090141cc406Sopenharmony_ci      max_pixel = s->params.pixels_per_line;
4091141cc406Sopenharmony_ci
4092141cc406Sopenharmony_ci      if (eight_bit_data)
4093141cc406Sopenharmony_ci        for (line = 1; line <= max_line; line++)
4094141cc406Sopenharmony_ci          {
4095141cc406Sopenharmony_ci            red = &(s->buffer[line * s->params.bytes_per_line]);
4096141cc406Sopenharmony_ci            green = &(red[max_pixel]);
4097141cc406Sopenharmony_ci            blue = &(green[max_pixel]);
4098141cc406Sopenharmony_ci            for (pixel = 0; pixel < max_pixel; pixel++)
4099141cc406Sopenharmony_ci              {
4100141cc406Sopenharmony_ci                *dest++ = *red++;
4101141cc406Sopenharmony_ci                *dest++ = *green++;
4102141cc406Sopenharmony_ci                *dest++ = *blue++;
4103141cc406Sopenharmony_ci              }
4104141cc406Sopenharmony_ci          }
4105141cc406Sopenharmony_ci      else
4106141cc406Sopenharmony_ci        for (line = 0; line < max_line; line++)
4107141cc406Sopenharmony_ci          {
4108141cc406Sopenharmony_ci            red = &(s->buffer[start_input + line * bytes_per_line_in]);
4109141cc406Sopenharmony_ci            green = &(red[(max_pixel+7)/8]);
4110141cc406Sopenharmony_ci            blue = &(green[(max_pixel+7)/8]);
4111141cc406Sopenharmony_ci            mask = 0x80;
4112141cc406Sopenharmony_ci            for (pixel = 0; pixel < max_pixel; pixel++)
4113141cc406Sopenharmony_ci              {
4114141cc406Sopenharmony_ci                *dest++ = (*red & mask)   ? 0xff : 0;
4115141cc406Sopenharmony_ci                *dest++ = (*green & mask) ? 0xff : 0;
4116141cc406Sopenharmony_ci                *dest++ = (*blue & mask)  ? 0xff : 0;
4117141cc406Sopenharmony_ci                mask = mask >> 1;
4118141cc406Sopenharmony_ci                if (mask == 0)
4119141cc406Sopenharmony_ci                  {
4120141cc406Sopenharmony_ci                    mask = 0x80;
4121141cc406Sopenharmony_ci                    red++;
4122141cc406Sopenharmony_ci                    green++;
4123141cc406Sopenharmony_ci                    blue++;
4124141cc406Sopenharmony_ci                  }
4125141cc406Sopenharmony_ci              }
4126141cc406Sopenharmony_ci          }
4127141cc406Sopenharmony_ci
4128141cc406Sopenharmony_ci      transfer = max_len;
4129141cc406Sopenharmony_ci      if (transfer > s->buf_used)
4130141cc406Sopenharmony_ci        transfer = s->buf_used;
4131141cc406Sopenharmony_ci      memcpy(&(dst_buf[*len]), s->buffer, transfer);
4132141cc406Sopenharmony_ci
4133141cc406Sopenharmony_ci      max_len -= transfer;
4134141cc406Sopenharmony_ci      s->buf_pos += transfer;
4135141cc406Sopenharmony_ci      *len += transfer;
4136141cc406Sopenharmony_ci    }
4137141cc406Sopenharmony_ci
4138141cc406Sopenharmony_ci  if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used)
4139141cc406Sopenharmony_ci    do_cancel (s);
4140141cc406Sopenharmony_ci  DBG (10, ">>\n");
4141141cc406Sopenharmony_ci  return (SANE_STATUS_GOOD);
4142141cc406Sopenharmony_ci}
4143141cc406Sopenharmony_ci
4144141cc406Sopenharmony_ciSANE_Status
4145141cc406Sopenharmony_cisane_read (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len,
4146141cc406Sopenharmony_ci	   SANE_Int * len)
4147141cc406Sopenharmony_ci{
4148141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
4149141cc406Sopenharmony_ci  SANE_Status status;
4150141cc406Sopenharmony_ci
4151141cc406Sopenharmony_ci  s->busy = SANE_TRUE;
4152141cc406Sopenharmony_ci  if (s->cancel == SANE_TRUE)
4153141cc406Sopenharmony_ci    {
4154141cc406Sopenharmony_ci      do_cancel(s);
4155141cc406Sopenharmony_ci      *len = 0;
4156141cc406Sopenharmony_ci      return (SANE_STATUS_CANCELLED);
4157141cc406Sopenharmony_ci    }
4158141cc406Sopenharmony_ci
4159141cc406Sopenharmony_ci  /* RGB scans with a JX 250 and bi-level color scans
4160141cc406Sopenharmony_ci     must be handled differently: */
4161141cc406Sopenharmony_ci  if (s->image_composition <= 2)
4162141cc406Sopenharmony_ci    status = sane_read_direct(handle, dst_buf, max_len, len);
4163141cc406Sopenharmony_ci  else if (s->image_composition <= 4)
4164141cc406Sopenharmony_ci    status = sane_read_shuffled(handle, dst_buf, max_len, len, 0);
4165141cc406Sopenharmony_ci  else if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350 )
4166141cc406Sopenharmony_ci    status = sane_read_direct(handle, dst_buf, max_len, len);
4167141cc406Sopenharmony_ci  else
4168141cc406Sopenharmony_ci    status = sane_read_shuffled(handle, dst_buf, max_len, len, 1);
4169141cc406Sopenharmony_ci
4170141cc406Sopenharmony_ci  s->busy = SANE_FALSE;
4171141cc406Sopenharmony_ci  if (s->cancel == SANE_TRUE)
4172141cc406Sopenharmony_ci    {
4173141cc406Sopenharmony_ci      do_cancel(s);
4174141cc406Sopenharmony_ci      return (SANE_STATUS_CANCELLED);
4175141cc406Sopenharmony_ci    }
4176141cc406Sopenharmony_ci
4177141cc406Sopenharmony_ci  return (status);
4178141cc406Sopenharmony_ci}
4179141cc406Sopenharmony_ci
4180141cc406Sopenharmony_civoid
4181141cc406Sopenharmony_cisane_cancel (SANE_Handle handle)
4182141cc406Sopenharmony_ci{
4183141cc406Sopenharmony_ci  SHARP_Scanner *s = handle;
4184141cc406Sopenharmony_ci  DBG (10, "<< sane_cancel ");
4185141cc406Sopenharmony_ci
4186141cc406Sopenharmony_ci  s->cancel = SANE_TRUE;
4187141cc406Sopenharmony_ci  if (s->busy == SANE_FALSE)
4188141cc406Sopenharmony_ci      do_cancel(s);
4189141cc406Sopenharmony_ci
4190141cc406Sopenharmony_ci  DBG (10, ">>\n");
4191141cc406Sopenharmony_ci}
4192141cc406Sopenharmony_ci
4193141cc406Sopenharmony_ciSANE_Status
4194141cc406Sopenharmony_cisane_set_io_mode (SANE_Handle __sane_unused__ handle,
4195141cc406Sopenharmony_ci		  SANE_Bool __sane_unused__ non_blocking)
4196141cc406Sopenharmony_ci{
4197141cc406Sopenharmony_ci  DBG (10, "<< sane_set_io_mode");
4198141cc406Sopenharmony_ci  DBG (10, ">>\n");
4199141cc406Sopenharmony_ci
4200141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
4201141cc406Sopenharmony_ci}
4202141cc406Sopenharmony_ci
4203141cc406Sopenharmony_ciSANE_Status
4204141cc406Sopenharmony_cisane_get_select_fd (SANE_Handle __sane_unused__ handle,
4205141cc406Sopenharmony_ci		    SANE_Int __sane_unused__ * fd)
4206141cc406Sopenharmony_ci{
4207141cc406Sopenharmony_ci  DBG (10, "<< sane_get_select_fd");
4208141cc406Sopenharmony_ci  DBG (10, ">>\n");
4209141cc406Sopenharmony_ci
4210141cc406Sopenharmony_ci  return SANE_STATUS_UNSUPPORTED;
4211141cc406Sopenharmony_ci}
4212