1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 2007 Jeremy Johnson
3    This file is part of a SANE backend for Ricoh IS450
4    and IS420 family of HS2P Scanners using the SCSI controller.
5 
6    This file is part of the SANE package.
7 
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 
21    As a special exception, the authors of SANE give permission for
22    additional uses of the libraries contained in this release of SANE.
23 
24    The exception is that, if you link a SANE library with other files
25    to produce an executable, this does not by itself cause the
26    resulting executable to be covered by the GNU General Public
27    License.  Your use of that executable is in no way restricted on
28    account of linking the SANE library code into it.
29 
30    This exception does not, however, invalidate any other reasons why
31    the executable file might be covered by the GNU General Public
32    License.
33 
34    If you submit changes to SANE to the maintainers to be included in
35    a subsequent release, you agree by submitting the changes that
36    those changes may be distributed with this exception intact.
37 
38    If you write modifications of your own for SANE, it is your choice
39    whether to permit this exception to apply to your modifications.
40    If you do not wish that, delete this exception notice.
41 
42 */
43 /* SANE-FLOW-DIAGRAM
44 
45    - sane_init() : initialize backend, attach scanners
46    . - sane_get_devices() : query list of scanner-devices
47    . - sane_open() : open a particular scanner-device
48    . . - attach : to the device
49    . . . init_options : initialize SANE_OPTIONS array
50    . . - sane_set_io_mode : set blocking-mode
51    . . - sane_get_select_fd : get scanner-fd
52    . . - sane_get_option_descriptor() : get option information
53    . . - sane_control_option() : change option values
54    . .
55    . . - sane_start() : start image acquisition
56    . .   - sane_get_parameters() : returns actual scan-parameters
57    . .   - sane_read() : read image-data (from pipe)
58    . .
59    . . - sane_cancel() : cancel operation
60    . - sane_close() : close opened scanner-device
61    - sane_exit() : terminate use of backend
62 */
63 #define BUILD 1
64 
65 /* Begin includes */
66 #include "../include/sane/config.h"
67 
68 #include <limits.h>
69 #include <stdlib.h>
70 #include <stdarg.h>
71 #include <string.h>
72 #include <sys/time.h>
73 #include <errno.h>
74 #include <fcntl.h>
75 #include <ctype.h>
76 #include <stdio.h>
77 #include <unistd.h>
78 #include <sys/types.h>
79 
80 #include "../include/sane/sane.h"
81 #include "../include/sane/saneopts.h"
82 #include "../include/sane/sanei_scsi.h"
83 #include "../include/sane/sanei_config.h"
84 #include "../include/sane/sanei_thread.h"
85 
86 #define BACKEND_NAME hs2p
87 #include "../include/sane/sanei_backend.h"
88 
89 #ifndef PATH_MAX
90 # define PATH_MAX	1024
91 #endif
92 
93 #include "hs2p-scsi.c"
94 
95 /* Begin macros */
96 #define MIN(x,y) ((x)<(y) ? (x) : (y))
97 #define MAX(x,y) ((x)>(y) ? (x) : (y))
98 
99 /* Begin static constants */
100 static int num_devices = 0;
101 static HS2P_Device *first_dev = NULL;
102 static HS2P_Scanner *first_handle = NULL;
103 
104 static SANE_Char inquiry_data[255] = "HS2P scanner";
105 /*
106 static SANE_Int disable_optional_frames = 0;
107 static SANE_Int fake_inquiry = 0;
108 */
109 
110 static HS2P_HWEntry HS2P_Device_List[] = {
111   {"RICOH", "IS450"},
112   {"RICOH", "IS430"},		/*untested */
113   {"RICOH", "IS420"},		/*untested */
114   {"RICOH", "IS01"},		/*untested */
115   {"RICOH", "IS02"},		/*untested */
116   {NULL, NULL}			/*sentinel */
117 };
118 
119 #if 0
120 static int
121 allblank (const char *s)
122 {
123   while (s && *s)
124     if (!isspace (*s++))
125       return 0;
126 
127   return 1;
128 }
129 #endif
130 
131 static size_t
max_string_size(SANE_String_Const strings[])132 max_string_size (SANE_String_Const strings[])
133 {
134   size_t size, max_size = 0;
135   int i;
136   DBG (DBG_proc, ">> max_string_size\n");
137 
138   for (i = 0; strings[i]; ++i)
139     {
140       size = strlen (strings[i]) + 1;
141       if (size > max_size)
142 	max_size = size;
143     }
144 
145   DBG (DBG_proc, "<< max_string_size\n");
146   return max_size;
147 }
148 
149 static void
trim_spaces(char * s,size_t n)150 trim_spaces (char *s, size_t n)
151 {
152   for (s += (n - 1); n > 0; n--, s--)
153     {
154       if (*s && !isspace (*s))
155 	break;
156       *s = '\0';
157     }
158 }
159 static SANE_Bool
is_device_supported(char * device)160 is_device_supported (char *device)
161 {
162   HS2P_HWEntry *hw;
163 
164   for (hw = &HS2P_Device_List[0]; hw->mfg != NULL; hw++)
165     if (strncmp (device, hw->model, strlen (hw->model)) == 0)
166       break;			/* found a match */
167 
168   return (hw == NULL) ? SANE_FALSE : SANE_TRUE;
169 }
170 
171 static SANE_Int
get_list_index(const char * list[],char * s)172 get_list_index (const char *list[], char *s)	/* sequential search */
173 {
174   SANE_Int i;
175 
176   for (i = 0; list[i]; i++)
177     if (strcmp (s, list[i]) == 0)
178       return i;			/* FOUND */
179 
180   /* unknown paper_list strings are treated as 'custom'     */
181   /* unknown compression_list strings are treated as 'none' */
182   /* unknown scan_source_list strings are treated as 'ADF'  */
183   return 0;
184 }
185 
186 static SANE_Int
get_val_id_strndx(struct val_id * vi,int len,SANE_Int val)187 get_val_id_strndx (struct val_id *vi, int len, SANE_Int val)
188 {
189   int i;
190   for (i = 0; i < len; i++)
191     if (vi[i].val == val)
192       return vi[i].id;		/* FOUND */
193   return vi[0].id;		/* NOT FOUND so let's default to first */
194 }
195 
196 static SANE_Status
init_options(HS2P_Scanner * s)197 init_options (HS2P_Scanner * s)
198 {
199   SANE_Int i;
200   DBG (DBG_proc, ">> init_options\n");
201 
202   memset (s->opt, 0, sizeof (s->opt));
203   memset (s->val, 0, sizeof (s->val));
204 
205   for (i = 0; i < NUM_OPTIONS; ++i)
206     {
207       s->opt[i].size = sizeof (SANE_Word);
208       s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
209     }
210 
211   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
212   s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
213   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
214   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
215   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
216 
217 
218   /*
219    * "Scan Mode" GROUP:
220    */
221   s->opt[OPT_MODE_GROUP].name = "";
222   s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP;
223   s->opt[OPT_MODE_GROUP].desc = "";
224   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
225   s->opt[OPT_MODE_GROUP].cap = 0;
226   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
227 
228   /* Preview: */
229   s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
230   s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
231   s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
232   s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
233   s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
234   s->val[OPT_PREVIEW].w = SANE_FALSE;
235 
236   /* Inquiry */
237   s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY;
238   s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY;
239   s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY;
240   s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING;
241   s->opt[OPT_INQUIRY].size = sizeof (inquiry_data);
242   s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE;
243   s->val[OPT_INQUIRY].s = strdup (inquiry_data);
244   s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT;	/* Display Only */
245 
246   /* Scan mode */
247   s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE;
248   s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
249   s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE;
250   s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING;
251   s->opt[OPT_SCAN_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
252   s->opt[OPT_SCAN_MODE].size =
253     max_string_size ((SANE_String_Const *) scan_mode_list);
254   s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
255   s->opt[OPT_SCAN_MODE].constraint.string_list =
256     (SANE_String_Const *) & scan_mode_list[0];
257   s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]);
258   s->image_composition = LINEART;
259 
260   /* Standard resolutions */
261   s->opt[OPT_RESOLUTION].name = "std-" SANE_NAME_SCAN_RESOLUTION;
262   s->opt[OPT_RESOLUTION].title = "Std-" SANE_TITLE_SCAN_RESOLUTION;
263   s->opt[OPT_RESOLUTION].desc = "Std " SANE_DESC_SCAN_RESOLUTION;
264   s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
265   s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
266   s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
267   s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList;
268   s->val[OPT_RESOLUTION].w = s->hw->info.default_res;
269 
270   /* X Resolution */
271   s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
272   s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION;
273   s->opt[OPT_X_RESOLUTION].desc = "X " SANE_DESC_SCAN_RESOLUTION;
274   s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
275   s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
276   s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
277   s->opt[OPT_X_RESOLUTION].constraint.range = &(s->hw->info.xres_range);
278   s->val[OPT_X_RESOLUTION].w = s->hw->info.resBasicX;
279 
280   /* Y Resolution */
281   s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION;
282   s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION;
283   s->opt[OPT_Y_RESOLUTION].desc = "Y " SANE_DESC_SCAN_RESOLUTION;
284   s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
285   s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
286   s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
287   s->opt[OPT_Y_RESOLUTION].constraint.range = &(s->hw->info.yres_range);
288   s->val[OPT_Y_RESOLUTION].w = s->hw->info.resBasicY;
289 
290   /* Compression */
291   s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION;
292   s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION;
293   s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION;
294   s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING;
295   s->opt[OPT_COMPRESSION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
296   s->opt[OPT_COMPRESSION].size =
297     max_string_size ((SANE_String_Const *) compression_list);
298   s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
299   s->opt[OPT_COMPRESSION].constraint.string_list =
300     (SANE_String_Const *) & compression_list[0];
301   s->val[OPT_COMPRESSION].s = strdup (compression_list[0]);
302   if (s->hw->info.supports_MH == SANE_FALSE ||	/* MH  G3 1-D       */
303       s->hw->info.supports_MR == SANE_FALSE ||	/* MR  G3 2-D       */
304       s->hw->info.supports_MMR == SANE_FALSE ||	/* MMR G4 2-D       */
305       s->hw->info.supports_MHB == SANE_FALSE)	/* MH byte boundary */
306     {
307       s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE;
308     }
309 
310 
311 
312   /*
313    * "Geometry" GROUP:
314    */
315   s->opt[OPT_GEOMETRY_GROUP].name = "";
316   s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP;
317   s->opt[OPT_GEOMETRY_GROUP].desc = "";
318   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
319   s->opt[OPT_GEOMETRY_GROUP].cap = 0;
320   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
321 
322   /* Auto Size Recognition available if IPU installed */
323   s->opt[OPT_AUTO_SIZE].name = SANE_NAME_AUTO_SIZE;
324   s->opt[OPT_AUTO_SIZE].title = SANE_TITLE_AUTO_SIZE;
325   s->opt[OPT_AUTO_SIZE].desc = SANE_DESC_AUTO_SIZE;
326   s->opt[OPT_AUTO_SIZE].type = SANE_TYPE_BOOL;
327   s->opt[OPT_AUTO_SIZE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
328   s->opt[OPT_AUTO_SIZE].constraint_type = SANE_CONSTRAINT_NONE;
329   s->val[OPT_AUTO_SIZE].w = SANE_FALSE;
330   if (!s->hw->info.supports_sizerecognition)
331     s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE;
332 
333   /* Pad short documents to requested length with white space */
334   s->opt[OPT_PADDING].name = SANE_NAME_PADDING;
335   s->opt[OPT_PADDING].title = SANE_TITLE_PADDING;
336   s->opt[OPT_PADDING].desc = SANE_DESC_PADDING;
337   s->opt[OPT_PADDING].type = SANE_TYPE_BOOL;
338   s->opt[OPT_PADDING].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
339   s->opt[OPT_PADDING].constraint_type = SANE_CONSTRAINT_NONE;
340   s->val[OPT_PADDING].w = SANE_TRUE;
341   /*if (!s->hw->info.hasADF)
342      s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
343      FIXME: compare to user setting, not the existence of FB?
344      if (!strcmp (scan_source_list, "FB"))
345      s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; */
346   /* Permanently disable OPT_PADDING */
347   s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
348 
349   /* Paper Orientation */
350   s->opt[OPT_PAGE_ORIENTATION].name = SANE_NAME_ORIENTATION;
351   s->opt[OPT_PAGE_ORIENTATION].title = SANE_TITLE_ORIENTATION;
352   s->opt[OPT_PAGE_ORIENTATION].desc = SANE_DESC_ORIENTATION;
353   s->opt[OPT_PAGE_ORIENTATION].type = SANE_TYPE_STRING;
354   s->opt[OPT_PAGE_ORIENTATION].size = max_string_size (orientation_list);
355   s->opt[OPT_PAGE_ORIENTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
356   s->opt[OPT_PAGE_ORIENTATION].constraint.string_list = &orientation_list[0];
357   s->val[OPT_PAGE_ORIENTATION].s = strdup (orientation_list[0]);
358 
359   /* Paper Size */
360   s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE;
361   s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE;
362   s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE;
363   s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING;
364   s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list);
365   s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
366   s->opt[OPT_PAPER_SIZE].constraint.string_list = &paper_list[0];
367   s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]);
368 
369   /* top-left x */
370   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
371   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
372   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
373   s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
374   s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
375   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
376   s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range);
377   s->val[OPT_TL_X].w = SANE_FIX (0.0);
378 
379   /* top-left y */
380   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
381   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
382   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
383   s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
384   s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
385   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
386   s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range);
387   s->val[OPT_TL_Y].w = SANE_FIX (0.0);
388 
389   /* bottom-right x */
390   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
391   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
392   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
393   s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
394   s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
395   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
396   s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range);
397   s->val[OPT_BR_X].w = s->hw->info.x_range.max;
398 
399   /* bottom-right y */
400   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
401   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
402   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
403   s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
404   s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
405   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
406   s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range);
407   s->val[OPT_BR_Y].w = s->hw->info.y_range.max;
408 
409   DBG (DBG_info, "INIT_OPTIONS: ul(x,y) = (%d,%d)    br(x,y) = (%d,%d)\n",
410        (unsigned) SANE_UNFIX (s->val[OPT_TL_X].w),
411        (unsigned) SANE_UNFIX (s->val[OPT_TL_Y].w),
412        (unsigned) SANE_UNFIX (s->val[OPT_BR_X].w),
413        (unsigned) SANE_UNFIX (s->val[OPT_BR_Y].w));
414   /* Autoborder */
415   /* Rotation   */
416   /* Deskew     */
417 
418 
419 
420   /*
421    * "Feeder" GROUP:
422    */
423   s->opt[OPT_FEEDER_GROUP].name = "";
424   s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP;
425   s->opt[OPT_FEEDER_GROUP].desc = "";
426   s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP;
427   s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED;
428   s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
429 
430   /* Scan Source */
431   s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE;
432   s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
433   s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
434   s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING;
435   s->opt[OPT_SCAN_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
436   s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list);
437   s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
438   s->opt[OPT_SCAN_SOURCE].constraint.string_list =
439     (SANE_String_Const *) & scan_source_list[0];
440   s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]);
441   if (!s->hw->info.hasADF)
442     s->opt[OPT_SCAN_SOURCE].cap |= SANE_CAP_INACTIVE;
443 
444   /* Duplex: */
445   s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX;
446   s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX;
447   s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX;
448   s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL;
449   s->opt[OPT_DUPLEX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
450   s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE;
451   s->val[OPT_DUPLEX].w = s->hw->info.default_duplex;
452   if (!s->hw->info.hasDuplex)
453     s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE;
454 
455   /* Prefeed: */
456   s->opt[OPT_PREFEED].name = SANE_NAME_PREFEED;
457   s->opt[OPT_PREFEED].title = SANE_TITLE_PREFEED;
458   s->opt[OPT_PREFEED].desc = SANE_DESC_PREFEED;
459   s->opt[OPT_PREFEED].type = SANE_TYPE_BOOL;
460   s->opt[OPT_PREFEED].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
461   s->opt[OPT_PREFEED].constraint_type = SANE_CONSTRAINT_NONE;
462   s->val[OPT_PREFEED].w = SANE_FALSE;
463   s->opt[OPT_PREFEED].cap |= SANE_CAP_INACTIVE;
464 
465   /* Endorser: */
466   s->opt[OPT_ENDORSER].name = SANE_NAME_ENDORSER;
467   s->opt[OPT_ENDORSER].title = SANE_TITLE_ENDORSER;
468   s->opt[OPT_ENDORSER].desc = SANE_DESC_ENDORSER;
469   s->opt[OPT_ENDORSER].type = SANE_TYPE_BOOL;
470   s->opt[OPT_ENDORSER].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
471   s->opt[OPT_ENDORSER].constraint_type = SANE_CONSTRAINT_NONE;
472   s->val[OPT_ENDORSER].w = s->hw->info.endorser_control;
473   if (!s->hw->info.hasEndorser)
474     s->opt[OPT_ENDORSER].cap |= SANE_CAP_INACTIVE;
475 
476   /* Endorser String: */
477   s->opt[OPT_ENDORSER_STRING].name = SANE_NAME_ENDORSER_STRING;
478   s->opt[OPT_ENDORSER_STRING].title = SANE_TITLE_ENDORSER_STRING;
479   s->opt[OPT_ENDORSER_STRING].desc = SANE_DESC_ENDORSER_STRING;
480   s->opt[OPT_ENDORSER_STRING].type = SANE_TYPE_STRING;
481   s->opt[OPT_ENDORSER_STRING].cap =
482     SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
483   s->opt[OPT_ENDORSER_STRING].size = sizeof (s->hw->info.endorser_string);
484   s->opt[OPT_ENDORSER_STRING].constraint_type = SANE_CONSTRAINT_NONE;
485   s->val[OPT_ENDORSER_STRING].s = strdup (s->hw->info.endorser_string);
486   if (!s->hw->info.hasEndorser)
487     s->opt[OPT_ENDORSER_STRING].cap |= SANE_CAP_INACTIVE;
488 
489   /* Batch     */
490   /* Check ADF */
491   /* timeout ADF */
492   /* timeout Manual */
493 
494   /*
495    * "Enhancement" GROUP:
496    */
497   s->opt[OPT_ENHANCEMENT_GROUP].name = "";
498   s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP;
499   s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
500   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
501   s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
502   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
503 
504   /* Halftone Type */
505   s->opt[OPT_HALFTONE_CODE].name = SANE_NAME_HALFTONE_CODE;
506   s->opt[OPT_HALFTONE_CODE].title = SANE_TITLE_HALFTONE_CODE;
507   s->opt[OPT_HALFTONE_CODE].desc = SANE_DESC_HALFTONE_CODE;
508   s->opt[OPT_HALFTONE_CODE].type = SANE_TYPE_STRING;
509   s->opt[OPT_HALFTONE_CODE].size = max_string_size (halftone_code);
510   s->opt[OPT_HALFTONE_CODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
511   s->opt[OPT_HALFTONE_CODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
512   s->opt[OPT_HALFTONE_CODE].constraint.string_list =
513     (SANE_String_Const *) & halftone_code[0];
514   s->val[OPT_HALFTONE_CODE].s = strdup (halftone_code[0]);
515   if (s->image_composition == LINEART)
516     s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE;
517 
518   /* Halftone patterns */
519   s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
520   s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
521   s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
522   s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
523   s->opt[OPT_HALFTONE_PATTERN].size =
524     max_string_size ((SANE_String_Const *) halftone_pattern_list);
525   s->opt[OPT_HALFTONE_PATTERN].cap =
526     SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
527   s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
528   s->opt[OPT_HALFTONE_PATTERN].constraint.string_list =
529     (SANE_String_Const *) & halftone_pattern_list[0];
530   s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]);
531   if (s->image_composition == LINEART)
532     s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE;
533 
534   /* Gray Filter */
535   s->opt[OPT_GRAYFILTER].name = SANE_NAME_GRAYFILTER;
536   s->opt[OPT_GRAYFILTER].title = SANE_TITLE_GRAYFILTER;
537   s->opt[OPT_GRAYFILTER].desc = SANE_DESC_GRAYFILTER;
538   s->opt[OPT_GRAYFILTER].type = SANE_TYPE_STRING;
539   s->opt[OPT_GRAYFILTER].size = max_string_size (grayfilter_list);
540   s->opt[OPT_GRAYFILTER].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
541   s->opt[OPT_GRAYFILTER].constraint_type = SANE_CONSTRAINT_STRING_LIST;
542   s->opt[OPT_GRAYFILTER].constraint.string_list =
543     (SANE_String_Const *) & grayfilter_list[0];
544   s->val[OPT_GRAYFILTER].s = strdup (grayfilter_list[0]);
545 
546   /* Scan Wait Mode */
547   s->opt[OPT_SCAN_WAIT_MODE].name = SANE_NAME_SCAN_WAIT_MODE;
548   s->opt[OPT_SCAN_WAIT_MODE].title = SANE_TITLE_SCAN_WAIT_MODE;
549   s->opt[OPT_SCAN_WAIT_MODE].desc = SANE_DESC_SCAN_WAIT_MODE;
550   s->opt[OPT_SCAN_WAIT_MODE].type = SANE_TYPE_BOOL;
551   s->opt[OPT_SCAN_WAIT_MODE].unit = SANE_UNIT_NONE;
552   s->val[OPT_SCAN_WAIT_MODE].w =
553     (s->hw->info.scan_wait_mode) ? SANE_TRUE : SANE_FALSE;
554 
555   /* Brightness */
556   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
557   s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
558   s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
559   s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
560   s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
561   s->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT;
562   s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
563   s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->info.brightness_range;
564   s->val[OPT_BRIGHTNESS].w = 128;
565 
566   /* Threshold */
567   s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
568   s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
569   s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
570   s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
571   s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
572   s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
573   s->opt[OPT_THRESHOLD].constraint.range = &s->hw->info.threshold_range;
574   s->val[OPT_THRESHOLD].w = 128;
575 
576   /* Contrast */
577   s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
578   s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
579   s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
580   s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
581   s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
582   s->opt[OPT_CONTRAST].cap = SANE_CAP_SOFT_DETECT;
583   s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
584   s->opt[OPT_CONTRAST].constraint.range = &s->hw->info.contrast_range;
585   s->val[OPT_CONTRAST].w = 128;
586 
587   /* Gamma */
588   s->opt[OPT_GAMMA].name = SANE_NAME_GAMMA;
589   s->opt[OPT_GAMMA].title = SANE_TITLE_GAMMA;
590   s->opt[OPT_GAMMA].desc = SANE_DESC_GAMMA;
591   s->opt[OPT_GAMMA].type = SANE_TYPE_STRING;
592   s->opt[OPT_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
593   s->opt[OPT_GAMMA].size = max_string_size ((SANE_String_Const *) gamma_list);
594   /*
595      s->opt[OPT_GAMMA].type = SANE_TYPE_INT;
596      s->opt[OPT_GAMMA].unit = SANE_UNIT_NONE;
597      s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE;
598      s->opt[OPT_GAMMA].constraint.range = &u8_range;
599      s->val[OPT_GAMMA].w = 0;
600    */
601   s->opt[OPT_GAMMA].type = SANE_TYPE_STRING;
602   s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST;
603   s->opt[OPT_GAMMA].constraint.string_list =
604     (SANE_String_Const *) & gamma_list[0];
605   s->val[OPT_GAMMA].s = strdup (gamma_list[0]);
606 
607   /* custom-gamma table */
608   s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
609   s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
610   s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
611   s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
612   s->opt[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
613   s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE;
614   s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
615 
616   /* grayscale gamma vector */
617   s->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR;
618   s->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR;
619   s->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR;
620   s->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT;
621   s->opt[OPT_GAMMA_VECTOR_GRAY].cap |=
622     SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
623   s->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE;
624   s->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word);
625   s->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE;
626   s->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &u8_range;
627   s->val[OPT_GAMMA_VECTOR_GRAY].wa = s->gamma_table;
628   s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE;
629 
630 
631   /* Control Panel */
632   /* ACE Function  */
633   /* ACE Sensitivity */
634 
635   /* Binary Smoothing Filter */
636   s->opt[OPT_SMOOTHING].name = SANE_NAME_SMOOTHING;
637   s->opt[OPT_SMOOTHING].title = SANE_TITLE_SMOOTHING;
638   s->opt[OPT_SMOOTHING].desc = SANE_DESC_SMOOTHING;
639   s->opt[OPT_SMOOTHING].type = SANE_TYPE_BOOL;
640   s->opt[OPT_SMOOTHING].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
641   s->opt[OPT_SMOOTHING].constraint_type = SANE_CONSTRAINT_NONE;
642   s->val[OPT_SMOOTHING].w = SANE_FALSE;
643   if (!s->hw->info.hasIPU)
644     s->opt[OPT_SMOOTHING].cap |= SANE_CAP_INACTIVE;
645 
646   /* Binary Noise Removal Filter */
647   s->opt[OPT_NOISEREMOVAL].name = SANE_NAME_NOISEREMOVAL;
648   s->opt[OPT_NOISEREMOVAL].title = SANE_TITLE_NOISEREMOVAL;
649   s->opt[OPT_NOISEREMOVAL].desc = SANE_DESC_NOISEREMOVAL;
650   s->opt[OPT_NOISEREMOVAL].type = SANE_TYPE_STRING;
651   s->opt[OPT_NOISEREMOVAL].size = max_string_size (noisematrix_list);
652   s->opt[OPT_NOISEREMOVAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
653   s->opt[OPT_NOISEREMOVAL].constraint.string_list =
654     (SANE_String_Const *) & noisematrix_list[0];
655   s->val[OPT_NOISEREMOVAL].s = strdup (noisematrix_list[0]);
656   if (!s->hw->info.hasIPU)
657     s->opt[OPT_NOISEREMOVAL].cap |= SANE_CAP_INACTIVE;
658 
659   /* Automatic Separation */
660   s->opt[OPT_AUTOSEP].name = SANE_NAME_AUTOSEP;
661   s->opt[OPT_AUTOSEP].title = SANE_TITLE_AUTOSEP;
662   s->opt[OPT_AUTOSEP].desc = SANE_DESC_AUTOSEP;
663   s->opt[OPT_AUTOSEP].type = SANE_TYPE_STRING;
664   s->opt[OPT_AUTOSEP].size = max_string_size (auto_separation_list);
665   s->opt[OPT_AUTOSEP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
666   s->opt[OPT_AUTOSEP].constraint.string_list =
667     (SANE_String_Const *) & auto_separation_list[0];
668   s->val[OPT_AUTOSEP].s = strdup (auto_separation_list[0]);
669   if (!s->hw->info.hasIPU)
670     s->opt[OPT_AUTOSEP].cap |= SANE_CAP_INACTIVE;
671 
672   /* Automatic Binarization */
673   s->opt[OPT_AUTOBIN].name = SANE_NAME_AUTOBIN;
674   s->opt[OPT_AUTOBIN].title = SANE_TITLE_AUTOBIN;
675   s->opt[OPT_AUTOBIN].desc = SANE_DESC_AUTOBIN;
676   s->opt[OPT_AUTOBIN].type = SANE_TYPE_STRING;
677   s->opt[OPT_AUTOBIN].size = max_string_size (auto_binarization_list);
678   s->opt[OPT_AUTOBIN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
679   s->opt[OPT_AUTOBIN].constraint.string_list =
680     (SANE_String_Const *) & auto_binarization_list[0];
681   s->val[OPT_AUTOBIN].s = strdup (auto_binarization_list[0]);
682   if (!s->hw->info.hasIPU)
683     s->opt[OPT_AUTOBIN].cap |= SANE_CAP_INACTIVE;
684 
685   /* SECTION
686    * The IS450 supports up to 4 Section; The IS420 supports up to 6 Sections
687    * For each struct window_section[i] we need to fill in ulx,uly,width,height,etc
688    * NOT YET IMPLEMENTED
689    */
690 
691   /* Negative */
692   s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
693   s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
694   s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
695   s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
696   s->opt[OPT_NEGATIVE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
697   s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
698   s->val[OPT_NEGATIVE].w = SANE_FALSE;
699 
700   /* White Balance */
701   s->opt[OPT_WHITE_BALANCE].name = SANE_NAME_WHITE_BALANCE;
702   s->opt[OPT_WHITE_BALANCE].title = SANE_TITLE_WHITE_BALANCE;
703   s->opt[OPT_WHITE_BALANCE].desc = SANE_DESC_WHITE_BALANCE;
704   s->opt[OPT_WHITE_BALANCE].type = SANE_TYPE_BOOL;
705   s->opt[OPT_WHITE_BALANCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
706   s->opt[OPT_WHITE_BALANCE].constraint_type = SANE_CONSTRAINT_NONE;
707   s->val[OPT_WHITE_BALANCE].w = SANE_FALSE;	/* F/T = Relative/Absolute White */
708 
709   /*
710    * "Miscellaneous" GROUP:
711    */
712   s->opt[OPT_MISCELLANEOUS_GROUP].name = "";
713   s->opt[OPT_MISCELLANEOUS_GROUP].title = SANE_TITLE_MISCELLANEOUS_GROUP;
714   s->opt[OPT_MISCELLANEOUS_GROUP].desc = "";
715   s->opt[OPT_MISCELLANEOUS_GROUP].type = SANE_TYPE_GROUP;
716   s->opt[OPT_MISCELLANEOUS_GROUP].cap = SANE_CAP_ADVANCED;
717   s->opt[OPT_MISCELLANEOUS_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
718 
719   /* Padding Type: */
720   s->opt[OPT_PADDING_TYPE].name = SANE_NAME_PADDING_TYPE;
721   s->opt[OPT_PADDING_TYPE].title = SANE_TITLE_PADDING_TYPE;
722   s->opt[OPT_PADDING_TYPE].desc = SANE_DESC_PADDING_TYPE;
723   s->opt[OPT_PADDING_TYPE].type = SANE_TYPE_STRING;
724   s->opt[OPT_PADDING_TYPE].cap = SANE_CAP_SOFT_DETECT;	/* Display only */
725   s->opt[OPT_PADDING_TYPE].size = max_string_size (paddingtype_list);
726   /*
727      s->opt[OPT_PADDING_TYPE].size = sizeof((paddingtype_list[ get_paddingtype_strndx(TRUNCATE) ]));
728      s->opt[OPT_PADDING_TYPE].constraint_type = SANE_CONSTRAINT_NONE;
729    */
730   s->opt[OPT_PADDING_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
731   s->opt[OPT_PADDING_TYPE].constraint.string_list =
732     (SANE_String_Const *) & paddingtype_list[0];
733   s->val[OPT_PADDING_TYPE].s =
734     strdup (paddingtype_list[get_paddingtype_strndx (TRUNCATE)]);
735   DBG (DBG_info, "PADDINGTYPE =%s size=%d\n", s->val[OPT_PADDING_TYPE].s,
736        s->opt[OPT_PADDING_TYPE].size);
737 
738   /* Bit Order
739      s->opt[OPT_BITORDER].name = SANE_NAME_BITORDER;
740      s->opt[OPT_BITORDER].title = SANE_TITLE_BITORDER;
741      s->opt[OPT_BITORDER].desc = SANE_DESC_BITORDER;
742      s->opt[OPT_BITORDER].type = SANE_TYPE_WORD;
743      s->opt[OPT_BITORDER].cap = SANE_CAP_SOFT_DETECT;
744      s->opt[OPT_BITORDER].constraint_type = SANE_CONSTRAINT_NONE
745      s->val[OPT_BITORDER].w =  0x7;
746    */
747 
748   /* Self Diagnostics */
749   s->opt[OPT_SELF_DIAGNOSTICS].name = SANE_NAME_SELF_DIAGNOSTICS;
750   s->opt[OPT_SELF_DIAGNOSTICS].title = SANE_TITLE_SELF_DIAGNOSTICS;
751   s->opt[OPT_SELF_DIAGNOSTICS].desc = SANE_DESC_SELF_DIAGNOSTICS;
752   s->opt[OPT_SELF_DIAGNOSTICS].type = SANE_TYPE_BUTTON;
753 
754   /* Optical Diagnostics */
755   s->opt[OPT_OPTICAL_ADJUSTMENT].name = SANE_NAME_OPTICAL_ADJUSTMENT;
756   s->opt[OPT_OPTICAL_ADJUSTMENT].title = SANE_TITLE_OPTICAL_ADJUSTMENT;
757   s->opt[OPT_OPTICAL_ADJUSTMENT].desc = SANE_DESC_OPTICAL_ADJUSTMENT;
758   s->opt[OPT_OPTICAL_ADJUSTMENT].type = SANE_TYPE_BUTTON;
759 
760   /* MAINTENANCE DATA */
761   s->opt[OPT_DATA_GROUP].name = "";
762   s->opt[OPT_DATA_GROUP].title = "Maintenance Data";
763   s->opt[OPT_DATA_GROUP].desc = "";
764   s->opt[OPT_DATA_GROUP].type = SANE_TYPE_GROUP;
765   s->opt[OPT_DATA_GROUP].cap = SANE_CAP_ADVANCED;
766   s->opt[OPT_DATA_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
767 
768   s->opt[OPT_UPDATE].name = "Update";
769   s->opt[OPT_UPDATE].title = "Update";
770   s->opt[OPT_UPDATE].desc = "Update scanner data";
771   s->opt[OPT_UPDATE].type = SANE_TYPE_BUTTON;
772   s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT;
773   s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE;
774 
775   s->opt[OPT_NREGX_ADF].name = "# registers in main-scanning in ADF mode";
776   s->opt[OPT_NREGX_ADF].title = "# registers in main-scanning in ADF mode";
777   s->opt[OPT_NREGX_ADF].desc = "# registers in main-scanning in ADF mode";
778   s->opt[OPT_NREGX_ADF].type = SANE_TYPE_INT;
779   s->opt[OPT_NREGX_ADF].unit = SANE_UNIT_NONE;
780   s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT;
781   s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE;
782 
783   s->opt[OPT_NREGY_ADF].name = "# registers in sub-scanning in ADF mode";
784   s->opt[OPT_NREGY_ADF].title = "# registers in sub-scanning in ADF mode";
785   s->opt[OPT_NREGY_ADF].desc = "# registers in sub-scanning in ADF mode";
786   s->opt[OPT_NREGY_ADF].type = SANE_TYPE_INT;
787   s->opt[OPT_NREGY_ADF].unit = SANE_UNIT_NONE;
788   s->opt[OPT_NREGY_ADF].cap = SANE_CAP_SOFT_DETECT;
789   s->opt[OPT_NREGY_ADF].constraint_type = SANE_CONSTRAINT_NONE;
790 
791   s->opt[OPT_NREGX_BOOK].name = "# registers in main-scanning in book mode";
792   s->opt[OPT_NREGX_BOOK].title = "# registers in main-scanning in book mode";
793   s->opt[OPT_NREGX_BOOK].desc = "# registers in main-scanning in book mode";
794   s->opt[OPT_NREGX_BOOK].type = SANE_TYPE_INT;
795   s->opt[OPT_NREGX_BOOK].unit = SANE_UNIT_NONE;
796   s->opt[OPT_NREGX_BOOK].cap = SANE_CAP_SOFT_DETECT;
797   s->opt[OPT_NREGX_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
798 
799   s->opt[OPT_NREGY_BOOK].name = "# registers in sub-scanning in book mode";
800   s->opt[OPT_NREGY_BOOK].title = "# registers in sub-scanning in book mode";
801   s->opt[OPT_NREGY_BOOK].desc = "# registers in sub-scanning in book mode";
802   s->opt[OPT_NREGY_BOOK].type = SANE_TYPE_INT;
803   s->opt[OPT_NREGY_BOOK].unit = SANE_UNIT_NONE;
804   s->opt[OPT_NREGY_BOOK].cap = SANE_CAP_SOFT_DETECT;
805   s->opt[OPT_NREGY_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
806 
807   s->opt[OPT_NSCANS_ADF].name = "# ADF Scans";
808   s->opt[OPT_NSCANS_ADF].title = "# ADF Scans";
809   s->opt[OPT_NSCANS_ADF].desc = "# ADF Scans";
810   s->opt[OPT_NSCANS_ADF].type = SANE_TYPE_INT;
811   s->opt[OPT_NSCANS_ADF].unit = SANE_UNIT_NONE;
812   s->opt[OPT_NSCANS_ADF].cap = SANE_CAP_SOFT_DETECT;
813   s->opt[OPT_NSCANS_ADF].constraint_type = SANE_CONSTRAINT_NONE;
814 
815   s->opt[OPT_NSCANS_BOOK].name = "# BOOK Scans";
816   s->opt[OPT_NSCANS_BOOK].title = "# BOOK Scans";
817   s->opt[OPT_NSCANS_BOOK].desc = "# BOOK Scans";
818   s->opt[OPT_NSCANS_BOOK].type = SANE_TYPE_INT;
819   s->opt[OPT_NSCANS_BOOK].unit = SANE_UNIT_NONE;
820   s->opt[OPT_NSCANS_BOOK].cap = SANE_CAP_SOFT_DETECT;
821   s->opt[OPT_NSCANS_BOOK].constraint_type = SANE_CONSTRAINT_NONE;
822 
823   s->opt[OPT_LAMP_TIME].name = "LAMP TIME";
824   s->opt[OPT_LAMP_TIME].title = "LAMP TIME";
825   s->opt[OPT_LAMP_TIME].desc = "LAMP TIME";
826   s->opt[OPT_LAMP_TIME].type = SANE_TYPE_INT;
827   s->opt[OPT_LAMP_TIME].unit = SANE_UNIT_NONE;
828   s->opt[OPT_LAMP_TIME].cap = SANE_CAP_SOFT_DETECT;
829   s->opt[OPT_LAMP_TIME].constraint_type = SANE_CONSTRAINT_NONE;
830 
831   s->opt[OPT_EO_ODD].name = "E/O Balance ODD";
832   s->opt[OPT_EO_ODD].title = "E/O Balance ODD";
833   s->opt[OPT_EO_ODD].desc = "Adj. of E/O Balance in black level ODD";
834   s->opt[OPT_EO_ODD].type = SANE_TYPE_INT;
835   s->opt[OPT_EO_ODD].unit = SANE_UNIT_NONE;
836   s->opt[OPT_EO_ODD].cap = SANE_CAP_SOFT_DETECT;
837   s->opt[OPT_EO_ODD].constraint_type = SANE_CONSTRAINT_NONE;
838 
839   s->opt[OPT_EO_EVEN].name = "E/O Balance EVEN";
840   s->opt[OPT_EO_EVEN].title = "E/O Balance EVEN";
841   s->opt[OPT_EO_EVEN].desc = "Adj. of E/O Balance in black level EVEN";
842   s->opt[OPT_EO_EVEN].type = SANE_TYPE_INT;
843   s->opt[OPT_EO_EVEN].unit = SANE_UNIT_NONE;
844   s->opt[OPT_EO_EVEN].cap = SANE_CAP_SOFT_DETECT;
845   s->opt[OPT_EO_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
846 
847   s->opt[OPT_BLACK_LEVEL_ODD].name = "Black Level ODD";
848   s->opt[OPT_BLACK_LEVEL_ODD].title = "Black Level ODD";
849   s->opt[OPT_BLACK_LEVEL_ODD].desc = "Adj. data in black level (ODD)";
850   s->opt[OPT_BLACK_LEVEL_ODD].type = SANE_TYPE_INT;
851   s->opt[OPT_BLACK_LEVEL_ODD].unit = SANE_UNIT_NONE;
852   s->opt[OPT_BLACK_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT;
853   s->opt[OPT_BLACK_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE;
854 
855   s->opt[OPT_BLACK_LEVEL_EVEN].name = "Black Level EVEN";
856   s->opt[OPT_BLACK_LEVEL_EVEN].title = "Black Level EVEN";
857   s->opt[OPT_BLACK_LEVEL_EVEN].desc = "Adj. data in black level (EVEN)";
858   s->opt[OPT_BLACK_LEVEL_EVEN].type = SANE_TYPE_INT;
859   s->opt[OPT_BLACK_LEVEL_EVEN].unit = SANE_UNIT_NONE;
860   s->opt[OPT_BLACK_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
861   s->opt[OPT_BLACK_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
862 
863   s->opt[OPT_WHITE_LEVEL_ODD].name = "White Level ODD";
864   s->opt[OPT_WHITE_LEVEL_ODD].title = "White Level ODD";
865   s->opt[OPT_WHITE_LEVEL_ODD].desc = "Adj. data in White level (ODD)";
866   s->opt[OPT_WHITE_LEVEL_ODD].type = SANE_TYPE_INT;
867   s->opt[OPT_WHITE_LEVEL_ODD].unit = SANE_UNIT_NONE;
868   s->opt[OPT_WHITE_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT;
869   s->opt[OPT_WHITE_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE;
870 
871   s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN";
872   s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN";
873   s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)";
874   s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT;
875   s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE;
876   s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
877   s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
878 
879   s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN";
880   s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN";
881   s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)";
882   s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT;
883   s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE;
884   s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT;
885   s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
886 
887   s->opt[OPT_DENSITY].name = "Density Adjustment";
888   s->opt[OPT_DENSITY].title = "Density Adjustment";
889   s->opt[OPT_DENSITY].desc = "Density adjustment of std. white board";
890   s->opt[OPT_DENSITY].type = SANE_TYPE_INT;
891   s->opt[OPT_DENSITY].unit = SANE_UNIT_NONE;
892   s->opt[OPT_DENSITY].cap = SANE_CAP_SOFT_DETECT;
893   s->opt[OPT_DENSITY].constraint_type = SANE_CONSTRAINT_NONE;
894 
895   s->opt[OPT_FIRST_ADJ_WHITE_ODD].name = "1st adj. in white level (ODD)";
896   s->opt[OPT_FIRST_ADJ_WHITE_ODD].title = "1st adj. in white level (ODD)";
897   s->opt[OPT_FIRST_ADJ_WHITE_ODD].desc = "1st adj. in white level (ODD)";
898   s->opt[OPT_FIRST_ADJ_WHITE_ODD].type = SANE_TYPE_INT;
899   s->opt[OPT_FIRST_ADJ_WHITE_ODD].unit = SANE_UNIT_NONE;
900   s->opt[OPT_FIRST_ADJ_WHITE_ODD].cap = SANE_CAP_SOFT_DETECT;
901   s->opt[OPT_FIRST_ADJ_WHITE_ODD].constraint_type = SANE_CONSTRAINT_NONE;
902 
903   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].name = "1st adj. in white level (EVEN)";
904   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].title = "1st adj. in white level (EVEN)";
905   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].desc = "1st adj. in white level (EVEN)";
906   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].type = SANE_TYPE_INT;
907   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].unit = SANE_UNIT_NONE;
908   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].cap = SANE_CAP_SOFT_DETECT;
909   s->opt[OPT_FIRST_ADJ_WHITE_EVEN].constraint_type = SANE_CONSTRAINT_NONE;
910 
911   s->opt[OPT_NREGX_REVERSE].name = "# registers of main-scanning of backside";
912   s->opt[OPT_NREGX_REVERSE].title =
913     "# registers of main-scanning of backside";
914   s->opt[OPT_NREGX_REVERSE].desc =
915     "# registers of main-scanning of ADF backside";
916   s->opt[OPT_NREGX_REVERSE].type = SANE_TYPE_INT;
917   s->opt[OPT_NREGX_REVERSE].unit = SANE_UNIT_NONE;
918   s->opt[OPT_NREGX_REVERSE].cap = SANE_CAP_SOFT_DETECT;
919   s->opt[OPT_NREGX_REVERSE].constraint_type = SANE_CONSTRAINT_NONE;
920 
921   s->opt[OPT_NREGY_REVERSE].name = "# registers of sub-scanning of backside";
922   s->opt[OPT_NREGY_REVERSE].title = "# registers of sub-scanning of backside";
923   s->opt[OPT_NREGY_REVERSE].desc =
924     "# registers of sub-scanning of ADF backside";
925   s->opt[OPT_NREGY_REVERSE].type = SANE_TYPE_INT;
926   s->opt[OPT_NREGY_REVERSE].unit = SANE_UNIT_NONE;
927   s->opt[OPT_NREGY_REVERSE].cap = SANE_CAP_SOFT_DETECT;
928   s->opt[OPT_NREGY_REVERSE].constraint_type = SANE_CONSTRAINT_NONE;
929 
930   s->opt[OPT_NSCANS_REVERSE_ADF].name = "# of scans of reverse side in ADF";
931   s->opt[OPT_NSCANS_REVERSE_ADF].title = "# of scans of reverse side in ADF";
932   s->opt[OPT_NSCANS_REVERSE_ADF].desc = "# of scans of reverse side in ADF";
933   s->opt[OPT_NSCANS_REVERSE_ADF].type = SANE_TYPE_INT;
934   s->opt[OPT_NSCANS_REVERSE_ADF].unit = SANE_UNIT_NONE;
935   s->opt[OPT_NSCANS_REVERSE_ADF].cap = SANE_CAP_SOFT_DETECT;
936   s->opt[OPT_NSCANS_REVERSE_ADF].constraint_type = SANE_CONSTRAINT_NONE;
937 
938   s->opt[OPT_REVERSE_TIME].name = "LAMP TIME (reverse)";
939   s->opt[OPT_REVERSE_TIME].title = "LAMP TIME (reverse)";
940   s->opt[OPT_REVERSE_TIME].desc = "LAMP TIME (reverse)";
941   s->opt[OPT_REVERSE_TIME].type = SANE_TYPE_INT;
942   s->opt[OPT_REVERSE_TIME].unit = SANE_UNIT_NONE;
943   s->opt[OPT_REVERSE_TIME].cap = SANE_CAP_SOFT_DETECT;
944   s->opt[OPT_REVERSE_TIME].constraint_type = SANE_CONSTRAINT_NONE;
945 
946   s->opt[OPT_NCHARS].name = "# of endorser characters";
947   s->opt[OPT_NCHARS].title = "# of endorser characters";
948   s->opt[OPT_NCHARS].desc = "# of endorser characters";
949   s->opt[OPT_NCHARS].type = SANE_TYPE_INT;
950   s->opt[OPT_NCHARS].unit = SANE_UNIT_NONE;
951   s->opt[OPT_NCHARS].cap = SANE_CAP_SOFT_DETECT;
952   s->opt[OPT_NCHARS].constraint_type = SANE_CONSTRAINT_NONE;
953 
954   DBG (DBG_proc, "<< init_options\n");
955   return SANE_STATUS_GOOD;
956 }
957 
958 static SANE_Status
attach(SANE_String_Const devname,int __sane_unused__ connType,HS2P_Device ** devp)959 attach (SANE_String_Const devname, int __sane_unused__ connType,
960 	HS2P_Device ** devp)
961 {
962   SANE_Status status;
963   HS2P_Device *dev;
964   struct inquiry_standard_data ibuf;
965   struct inquiry_vpd_data vbuf;
966   struct inquiry_jis_data jbuf;
967   size_t buf_size;
968   int fd = -1;
969   double mm;
970 
971   char device_string[60];
972 
973   unsigned int i;
974   SANE_String *str;
975 
976 
977   DBG (DBG_sane_proc, ">>> attach:\n");
978 
979   for (dev = first_dev; dev; dev = dev->next)
980     {
981       if (strcmp (dev->sane.name, devname) == 0)
982 	{
983 	  if (devp)
984 	    *devp = dev;
985 	  return SANE_STATUS_GOOD;
986 	}
987     }
988   DBG (DBG_sane_proc, ">>> attach: opening \"%s\"\n", devname);
989 
990   /* sanei_scsi_open takes an option bufsize argument */
991   status = sanei_scsi_open (devname, &fd, &sense_handler, &(dev->sense_data));
992   if (status != SANE_STATUS_GOOD)
993     {
994       DBG (DBG_error, ">>> attach: open failed: %s\n",
995 	   sane_strstatus (status));
996       return (status);
997     }
998 
999   DBG (DBG_sane_proc, ">>> attach: opened %s fd=%d\n", devname, fd);
1000 
1001   DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (standard data)\n");
1002   memset (&ibuf, 0, sizeof (ibuf));
1003   buf_size = sizeof (ibuf);
1004   status = inquiry (fd, &ibuf, &buf_size, 0, HS2P_INQUIRY_STANDARD_PAGE_CODE);
1005   if (status != SANE_STATUS_GOOD)
1006     {
1007       DBG (DBG_error, ">>> attach: inquiry failed: %s\n",
1008 	   sane_strstatus (status));
1009       sanei_scsi_close (fd);
1010       return (status);
1011     }
1012 
1013   DBG (DBG_info,
1014        ">>> attach: reported devtype='%d', vendor='%.8s', product='%.16s', revision='%.4s'\n",
1015        ibuf.devtype, ibuf.vendor, ibuf.product, ibuf.revision);
1016   DBG (DBG_info,
1017        ">>> attach: reported RMB=%#x Ver=%#x ResponseDataFormat=%#x Length=%#x Byte7=%#x\n",
1018        ibuf.rmb_evpd, ibuf.version, ibuf.response_data_format, ibuf.length,
1019        ibuf.byte7);
1020 
1021   if (ibuf.devtype != 6 || strncmp ((char *) ibuf.vendor, "RICOH   ", 8) != 0)
1022     {
1023       DBG (DBG_warning, ">>> attach: device is not a RICOH scanner\n");
1024       sanei_scsi_close (fd);
1025       return SANE_STATUS_INVAL;
1026     }
1027   else if (!is_device_supported ((char *) ibuf.product))
1028     {
1029       DBG (DBG_warning,
1030 	   ">>> attach: device %s is not yet a supported RICOH scanner\n",
1031 	   ibuf.product);
1032       sanei_scsi_close (fd);
1033       return SANE_STATUS_INVAL;
1034     }
1035 
1036   /* We should now have an open file descriptor to a supported hs2p scanner */
1037   DBG (DBG_sane_proc, ">>> attach: sending TEST_UNIT_READY\n");
1038   do
1039     {
1040       status = test_unit_ready (fd);
1041     }
1042   while (status == HS2P_SK_UNIT_ATTENTION);
1043   if (status != HS2P_SCSI_STATUS_GOOD)
1044     {
1045       DBG (DBG_error, ">>> attach: test unit ready failed (%s)\n",
1046 	   sane_strstatus (status));
1047       sanei_scsi_close (fd);
1048       return (status);
1049     }
1050 
1051   DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (vpd data)\n");
1052   memset (&vbuf, 0, sizeof (vbuf));
1053   buf_size = sizeof (vbuf);
1054   status = inquiry (fd, &vbuf, &buf_size, 1, HS2P_INQUIRY_VPD_PAGE_CODE);
1055   if (status != SANE_STATUS_GOOD)
1056     {
1057       DBG (DBG_error, ">>> attach: inquiry (vpd data) failed: %s\n",
1058 	   sane_strstatus (status));
1059       sanei_scsi_close (fd);
1060       return status;
1061     }
1062   print_vpd_info (&vbuf);
1063 
1064   DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (jis data)\n");
1065   memset (&jbuf, 0, sizeof (jbuf));
1066   buf_size = sizeof (jbuf);
1067   status = inquiry (fd, &jbuf, &buf_size, 1, HS2P_INQUIRY_JIS_PAGE_CODE);
1068   if (status != SANE_STATUS_GOOD)
1069     {
1070       DBG (DBG_error, ">>> attach: inquiry (jis data) failed: %s\n",
1071 	   sane_strstatus (status));
1072       sanei_scsi_close (fd);
1073       return status;
1074     }
1075   print_jis_info (&jbuf);
1076 
1077 
1078   /* Fill in HS2P_Device {sane;info} */
1079   dev = malloc (sizeof (*dev));
1080   if (!dev)
1081     return SANE_STATUS_NO_MEM;
1082   memset (dev, 0, sizeof (*dev));
1083 
1084   /* Maximum Number of Sub-Sections of Main Scanning Window */
1085   if (strncmp ((char *) ibuf.product, "IS450", 5) == 0)
1086     {
1087       dev->info.max_win_sections = 4;
1088     }
1089   else if (strncmp ((char *) ibuf.product, "IS420", 5) == 0)
1090     {
1091       dev->info.max_win_sections = 6;
1092     }
1093 
1094   /* Some MODE SELECT scanner options */
1095   DBG (DBG_proc, ">>> attach: get_basic_measurement_unit\n");
1096   status =
1097     get_basic_measurement_unit (fd, &(dev->info.bmu), &(dev->info.mud));
1098   if (status != SANE_STATUS_GOOD)
1099     {
1100       DBG (DBG_error, ">>> attach: get_basic_measurement_unit failed (%s)\n",
1101 	   sane_strstatus (status));
1102       DBG (DBG_error, ">>> attach: setting to defaults\n");
1103       status = set_basic_measurement_unit (fd, MILLIMETERS);
1104       if (status != SANE_STATUS_GOOD)
1105 	{
1106 	  DBG (DBG_error,
1107 	       ">>> attach: set_basic_measurement_unit failed (%s)\n",
1108 	       sane_strstatus (status));
1109 	}
1110     }
1111   if ((status =
1112        get_connection_parameters (fd, &(dev->info.cxn))) != SANE_STATUS_GOOD)
1113     {
1114       DBG (DBG_error, ">>> attach: get_connection_parameters failed\n");
1115     }
1116   status = get_endorser_control (fd, &dev->info.endorser_control);
1117   if (status != SANE_STATUS_GOOD || dev->info.endorser_control != 0x01)
1118     {
1119       DBG (DBG_error,
1120 	   ">>> attach: get_endorser_control failed: return value=%#02x\n",
1121 	   dev->info.endorser_control);
1122       dev->info.endorser_control = 0x00;
1123     }
1124   if ((dev->info.service_mode = get_service_mode (fd)) != 0x00
1125       && dev->info.service_mode != 0x01)
1126     {
1127       DBG (DBG_error, ">>> attach: get_service_mode failed %#02x\n",
1128 	   dev->info.service_mode);
1129       dev->info.service_mode = 0x00;
1130     }
1131   if ((dev->info.scan_wait_mode = get_scan_wait_mode (fd)) != 0x00
1132       && dev->info.scan_wait_mode != 0x01)
1133     {
1134       DBG (DBG_error,
1135 	   ">>> attach: get_scan_wait_mode failed: return value=%#02x\n",
1136 	   dev->info.scan_wait_mode);
1137       dev->info.scan_wait_mode = 0x00;
1138     }
1139   status = get_white_balance (fd, &dev->info.white_balance);
1140   if (status != SANE_STATUS_GOOD && dev->info.white_balance != 0x01)
1141     {
1142       DBG (DBG_error,
1143 	   ">>> attach: get_white_balance failed: return value=%#02x\n",
1144 	   dev->info.white_balance);
1145       dev->info.white_balance = RELATIVE_WHITE;
1146     }
1147 
1148   DBG (DBG_info, ">>> attach: flushing and closing fd=%d\n", fd);
1149   sanei_scsi_req_flush_all ();
1150   sanei_scsi_close (fd);
1151 
1152   dev->info.devtype = ibuf.devtype;
1153   snprintf (dev->info.vendor, 9, "%-.5s", ibuf.vendor);	/* RICOH */
1154   trim_spaces (dev->info.vendor, sizeof (dev->info.vendor));
1155   snprintf (dev->info.product, 16, "%-.16s", ibuf.product);	/* IS450 */
1156   trim_spaces (dev->info.product, sizeof (dev->info.product));
1157   snprintf (dev->info.revision, 5, "%-.4s", ibuf.revision);	/* 1R04 */
1158   trim_spaces (dev->info.revision, sizeof (dev->info.revision));
1159 
1160   /* SANE_Device sane information */
1161   dev->sane.name = strdup (devname);
1162   dev->sane.vendor =
1163     (strcmp (dev->info.vendor, "RICOH") ==
1164      0) ? strdup ("Ricoh") : strdup (dev->info.vendor);
1165   dev->sane.model = strdup (dev->info.product);
1166   dev->sane.type = strdup ("sheetfed scanner");
1167   /*
1168      dev->sane.email_backend_author = strdup("<Jeremy Johnson> jeremy@acjlaw.net");
1169      dev->sane.backend_website = strdup("http://www.acjlaw.net:8080/~jeremy/Ricoh");
1170    */
1171   /* read these values from backend configuration file using parse_configuration
1172      dev->sane.location = strdup();
1173      dev->sane.comment = strdup();
1174      dev->sane.backend_version_code = strdup();
1175    */
1176   /* NOT YET USED */
1177   /* dev->sane.backend_capablity_flags = 0x00; */
1178 
1179   /* set capabilities from vpd */
1180   /* adf_id: 0=none,1=simplex,2=duplex,3=ARDF,4=reserved;  should be 1 or 2 for IS450 family */
1181   dev->info.hasADF = vbuf.adf_id == 0 ? SANE_FALSE : SANE_TRUE;
1182   dev->info.hasSimplex = vbuf.adf_id == 1 ? SANE_TRUE : SANE_FALSE;
1183   dev->info.hasDuplex = vbuf.adf_id == 2 ? SANE_TRUE : SANE_FALSE;
1184   dev->info.hasARDF = vbuf.adf_id == 3 ? SANE_TRUE : SANE_FALSE;
1185 
1186   /* end_id 0=none,1=Yes,2=reserved;  should always be 0 or 1 */
1187   dev->info.hasEndorser = vbuf.end_id == 1 ? SANE_TRUE : SANE_FALSE;
1188   for (i = 0; i < 20; i++)
1189     dev->info.endorser_string[i] = '\0';
1190 
1191   /* ipu_id: Bit0: '0'-no IPU, '1'-has IPU
1192    *         Bit1: '0'-no extended board, '1'-has extended board;
1193    * should always be 0
1194    */
1195   dev->info.hasIPU = (vbuf.ipu_id & 0x01) == 0x01 ? SANE_TRUE : SANE_FALSE;
1196   dev->info.hasXBD = (vbuf.ipu_id & 0x02) == 0x02 ? SANE_TRUE : SANE_FALSE;
1197 
1198 
1199   /* Image Composition Byte is set to 0x37 (0011 0111) */
1200   dev->info.supports_lineart = (vbuf.imagecomposition & 0x01) == 0x01 ? SANE_TRUE : SANE_FALSE;	/* TRUE */
1201   dev->info.supports_dithering = (vbuf.imagecomposition & 0x02) == 0x02 ? SANE_TRUE : SANE_FALSE;	/* TRUE */
1202   dev->info.supports_errordiffusion = (vbuf.imagecomposition & 0x04) == 0x04 ? SANE_TRUE : SANE_FALSE;	/* TRUE */
1203   dev->info.supports_color = (vbuf.imagecomposition & 0x08) == 0x08 ? SANE_TRUE : SANE_FALSE;	/* FALSE */
1204   dev->info.supports_4bitgray = (vbuf.imagecomposition & 0x10) == 0x10 ? SANE_TRUE : SANE_FALSE;	/* TRUE */
1205   dev->info.supports_8bitgray = (vbuf.imagecomposition & 0x20) == 0x20 ? SANE_TRUE : SANE_FALSE;	/* TRUE */
1206   /* vbuf.imagecomposition & 0x40; FALSE */
1207   /* vbuf.imagecomposition & 0x80  FALSE reserved */
1208   str = &scan_mode_list[0];	/* array of string pointers */
1209   if (dev->info.supports_lineart)
1210     *str++ = strdup (SM_LINEART);
1211   if (dev->info.supports_dithering || dev->info.supports_errordiffusion)
1212     *str++ = strdup (SM_HALFTONE);
1213   if (dev->info.supports_color)
1214     *str++ = strdup (SM_COLOR);
1215   if (dev->info.supports_4bitgray)
1216     *str++ = strdup (SM_4BITGRAY);
1217   if (dev->info.supports_8bitgray)
1218     *str++ = strdup (SM_8BITGRAY);
1219   *str = NULL;
1220 
1221   snprintf (device_string, 60, "Flatbed%s%s%s%s%s%s",
1222 	    dev->info.hasADF ? "/ADF" : "",
1223 	    dev->info.hasDuplex ? "/Duplex" : "",
1224 	    dev->info.hasEndorser ? "/Endorser" : "",
1225 	    dev->info.hasIPU ? "/IPU" : "",
1226 	    dev->info.supports_color ? " Color" : " B&W", " Scanner");
1227   dev->sane.type = strdup (device_string);
1228 
1229   /* ACE Image Data Processing  Binary Filters
1230    * For IS450 this is set to 0x18 (0001 1000) if IPU installed, else 0x00
1231    * For IS420 this is set to 0x3C (0011 1100) if IPU installed, else 0x00
1232    */
1233   dev->info.supports_whiteframing =
1234     ((vbuf.imagedataprocessing[0] & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE;
1235   dev->info.supports_blackframing =
1236     ((vbuf.imagedataprocessing[0] & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE;
1237   dev->info.supports_edgeextraction =
1238     ((vbuf.imagedataprocessing[0] & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE;
1239   dev->info.supports_noiseremoval =
1240     ((vbuf.imagedataprocessing[0] & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE;
1241   dev->info.supports_smoothing =
1242     ((vbuf.imagedataprocessing[0] & 0x10) == 0x10) ? SANE_TRUE : SANE_FALSE;
1243   dev->info.supports_linebolding =
1244     ((vbuf.imagedataprocessing[0] & 0x20) == 0x20) ? SANE_TRUE : SANE_FALSE;
1245 
1246   /* Compression Method is not supported for IS450
1247    *                    is     supported for IS420  */
1248   dev->info.supports_MH =
1249     ((vbuf.compression & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE;
1250   dev->info.supports_MR =
1251     ((vbuf.compression & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE;
1252   dev->info.supports_MMR =
1253     ((vbuf.compression & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE;
1254   dev->info.supports_MHB = ((vbuf.compression & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE;	/* MH Byte Boundary */
1255 
1256   /* compression_list[] will have variable number of elements, but the order will be fixed as follows: */
1257   str = &compression_list[0];
1258   *str++ = strdup ("none");
1259   if (dev->info.supports_MH)
1260     *str++ = strdup ("G3 1-D MH");
1261   if (dev->info.supports_MR)
1262     *str++ = strdup ("G3 2-D MR");
1263   if (dev->info.supports_MMR)
1264     *str++ = strdup ("G4 2-D MMR");
1265   if (dev->info.supports_MHB)
1266     *str++ = strdup ("MH Byte Boundary");
1267   *str = NULL;
1268 
1269   /* Marker Recognition is set to 0x00 */
1270   dev->info.supports_markerrecognition =
1271     ((vbuf.markerrecognition & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE;
1272 
1273   /* Size Recognition
1274    * For IS450 this is set to 0x01 when IPU installed; else 0x00
1275    * For IS420 this is set to 0x01
1276    */
1277   dev->info.supports_sizerecognition =
1278     ((vbuf.sizerecognition & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE;
1279 
1280   /* X Maximum Output Pixel in main scanning direction
1281    * For IS450 this is set to 0x1360 (4960)
1282    * For IS420 this is set to        (4880)
1283    * [MostSignificantByte LeastSignificantByte]
1284    */
1285   dev->info.xmaxoutputpixels =
1286     (vbuf.xmaxoutputpixels[0] << 8) | vbuf.xmaxoutputpixels[1];
1287 
1288   /* Set capabilities from jis VPD IDENTIFIER Page Code F0H */
1289   dev->info.resBasicX = _2btol (&jbuf.BasicRes.x[0]);	/* set to 400 */
1290   dev->info.resBasicY = _2btol (&jbuf.BasicRes.y[0]);	/* set to 400 */
1291 
1292   dev->info.resXstep = (jbuf.resolutionstep >> 4) & 0x0F;	/* set to 1   */
1293   dev->info.resYstep = jbuf.resolutionstep & 0x0F;	/* set to 1   */
1294   dev->info.resMaxX = _2btol (&jbuf.MaxRes.x[0]);	/* set to 800 */
1295   dev->info.resMaxY = _2btol (&jbuf.MaxRes.y[0]);	/* set to 800 */
1296   dev->info.resMinX = _2btol (&jbuf.MinRes.x[0]);	/* set to 100 for IS450 and 60 for IS420 */
1297   dev->info.resMinY = _2btol (&jbuf.MinRes.y[0]);	/* set to 100 for IS450 and 60 for IS420 */
1298 
1299   dev->info.xres_range.min = _2btol (&jbuf.MinRes.x[0]);	/* set to 100 for IS450 and 60 for IS420 */
1300   dev->info.xres_range.max = _2btol (&jbuf.MaxRes.x[0]);	/* set to 800 */
1301   dev->info.resXstep = (jbuf.resolutionstep >> 4) & 0x0F;	/* set to 1   */
1302   dev->info.xres_range.quant = dev->info.resXstep;
1303 
1304   dev->info.yres_range.min = _2btol (&jbuf.MinRes.y[0]);	/* set to 100 for IS450 and 60 for IS420 */
1305   dev->info.yres_range.max = _2btol (&jbuf.MaxRes.y[0]);	/* set to 800 */
1306   dev->info.resYstep = jbuf.resolutionstep & 0x0F;	/* set to 1   */
1307   dev->info.yres_range.quant = dev->info.resYstep;
1308 
1309   /* set the length of the list to zero first, then append standard resolutions */
1310   i = 0;
1311   if ((jbuf.standardres[0] & 0x80) == 0x80)
1312     dev->info.resStdList[++i] = 60;
1313   if ((jbuf.standardres[0] & 0x40) == 0x40)
1314     dev->info.resStdList[++i] = 75;
1315   if ((jbuf.standardres[0] & 0x20) == 0x20)
1316     dev->info.resStdList[++i] = 100;
1317   if ((jbuf.standardres[0] & 0x10) == 0x10)
1318     dev->info.resStdList[++i] = 120;
1319   if ((jbuf.standardres[0] & 0x08) == 0x08)
1320     dev->info.resStdList[++i] = 150;
1321   if ((jbuf.standardres[0] & 0x04) == 0x04)
1322     dev->info.resStdList[++i] = 160;
1323   if ((jbuf.standardres[0] & 0x02) == 0x02)
1324     dev->info.resStdList[++i] = 180;
1325   if ((jbuf.standardres[0] & 0x01) == 0x01)
1326     dev->info.resStdList[++i] = 200;
1327   if ((jbuf.standardres[1] & 0x80) == 0x80)
1328     dev->info.resStdList[++i] = 240;
1329   if ((jbuf.standardres[1] & 0x40) == 0x40)
1330     dev->info.resStdList[++i] = 300;
1331   if ((jbuf.standardres[1] & 0x20) == 0x20)
1332     dev->info.resStdList[++i] = 320;
1333   if ((jbuf.standardres[1] & 0x10) == 0x10)
1334     dev->info.resStdList[++i] = 400;
1335   if ((jbuf.standardres[1] & 0x08) == 0x08)
1336     dev->info.resStdList[++i] = 480;
1337   if ((jbuf.standardres[1] & 0x04) == 0x04)
1338     dev->info.resStdList[++i] = 600;
1339   if ((jbuf.standardres[1] & 0x02) == 0x02)
1340     dev->info.resStdList[++i] = 800;
1341   if ((jbuf.standardres[1] & 0x01) == 0x01)
1342     dev->info.resStdList[++i] = 1200;
1343   dev->info.resStdList[0] = i;	/* number of resolutions */
1344   if (dev->info.resStdList[0] == 0)
1345     {				/* make a default standard resolutions for 200 and 300dpi */
1346       DBG (DBG_warning, "attach: no standard resolutions reported\n");
1347       dev->info.resStdList[0] = 2;
1348       dev->info.resStdList[1] = 200;
1349       dev->info.resStdList[2] = 300;
1350       dev->info.resBasicX = dev->info.resBasicY = 300;
1351     }
1352   DBG (DBG_info, "attach: Window(W/L) = (%lu/%lu)\n",
1353        _4btol (&jbuf.Window.width[0]), _4btol (&jbuf.Window.length[0]));
1354   dev->info.winWidth = _4btol (&jbuf.Window.width[0]);
1355   dev->info.winHeight = _4btol (&jbuf.Window.length[0]);
1356   if (dev->info.winWidth <= 0)
1357     {
1358       dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5);
1359       DBG (DBG_warning, "attach: invalid window width reported, using %d\n",
1360 	   dev->info.winWidth);
1361     }
1362   if (dev->info.winHeight <= 0)
1363     {
1364       dev->info.winHeight = dev->info.resBasicY * 14;
1365       DBG (DBG_warning, "attach: invalid window height reported, using %d\n",
1366 	   dev->info.winHeight);
1367     }
1368   /* 4692 / 400 * 25.4 = 297 */
1369   mm = (dev->info.resBasicX > 0) ?
1370     ((double) dev->info.winWidth / (double) dev->info.resBasicX *
1371      MM_PER_INCH) : 0.0;
1372   dev->info.x_range.min = SANE_FIX (0.0);
1373   dev->info.x_range.max = SANE_FIX (mm);
1374   dev->info.x_range.quant = SANE_FIX (0.0);
1375   DBG (DBG_info, "attach: winWidth=%d resBasicX=%d mm/in=%f mm=%f\n",
1376        dev->info.winWidth, dev->info.resBasicX, MM_PER_INCH, mm);
1377 
1378   mm = (dev->info.resBasicY > 0) ?
1379     ((double) dev->info.winHeight / (double) dev->info.resBasicY *
1380      MM_PER_INCH) : 0.0;
1381   dev->info.y_range.min = SANE_FIX (0.0);
1382   dev->info.y_range.max = SANE_FIX (mm);
1383   dev->info.y_range.quant = SANE_FIX (0.0);
1384 
1385   DBG (DBG_info, "attach: RANGE x_range.max=%f, y_range.max=%f\n",
1386        SANE_UNFIX (dev->info.x_range.max),
1387        SANE_UNFIX (dev->info.y_range.max));
1388 
1389   /* min, max, quantization  light-dark  1-255, 0 means default 128 */
1390   dev->info.brightness_range.min = 1;
1391   dev->info.brightness_range.max = 255;
1392   dev->info.brightness_range.quant = 1;
1393   /* min, max, quantization  white-black 1-255, 0 means default 128 */
1394   dev->info.contrast_range.min = 1;
1395   dev->info.contrast_range.max = 255;
1396   dev->info.contrast_range.quant = 1;
1397   /* min, max, quantization  low-high    1-255, 0 means default 128 */
1398   dev->info.threshold_range.min = 1;
1399   dev->info.threshold_range.max = 255;
1400   dev->info.threshold_range.quant = 1;
1401 
1402   /* jbuf.functions */
1403   dev->info.overflow_support =
1404     ((jbuf.functions & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE;
1405   dev->info.lineart_support =
1406     ((jbuf.functions & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE;
1407   dev->info.dither_support =
1408     ((jbuf.functions & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE;
1409   dev->info.grayscale_support =
1410     ((jbuf.functions & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE;
1411 
1412   /* set option defaults  */
1413   dev->info.default_res = dev->info.resBasicX;
1414   dev->info.default_xres = dev->info.resBasicX;
1415   dev->info.default_yres = dev->info.resBasicY;
1416   dev->info.default_imagecomposition = LINEART;
1417   dev->info.default_media = FLATBED;
1418   dev->info.default_duplex = SANE_FALSE;
1419 
1420   /* dev->info.autoborder_default = dev->info.canBorderRecog; */
1421   /*
1422      dev->info.batch_default = SANE_FALSE;
1423      dev->info.deskew_default = SANE_FALSE;
1424      dev->info.check_adf_default = SANE_FALSE;
1425      dev->info.timeout_adf_default = 0;
1426      dev->info.timeout_manual_default = 0;
1427    */
1428   /* dev->info.control_panel_default = dev->info.canACE; Image Data Processing */
1429 
1430   ++num_devices;
1431   dev->next = first_dev;
1432   first_dev = dev;
1433 
1434   if (devp)
1435     *devp = dev;
1436 
1437   DBG (DBG_sane_proc, "<<< attach:\n");
1438   return SANE_STATUS_GOOD;
1439 }
1440 
1441 
1442 
1443 
1444 /* SANE callback to attach a SCSI device */
1445 static SANE_Status
attach_one_scsi(const char * devname)1446 attach_one_scsi (const char *devname)
1447 {
1448   return attach (devname, CONNECTION_SCSI, NULL);
1449   /* return SANE_STATUS_GOOD; */
1450 }
1451 
1452 static void
parse_configuration_file(FILE * fp)1453 parse_configuration_file (FILE * fp)
1454 {
1455   char line[PATH_MAX], *s, *t;
1456   int linenumber;
1457 
1458   DBG (DBG_proc, ">> parse_configuration_file\n");
1459 
1460   if (fp == NULL)
1461     {
1462       DBG (DBG_proc,
1463 	   ">> parse_configuration_file: No config file present!\n");
1464     }
1465   else
1466     {				/*parse configuration file */
1467       for (linenumber = 0; sanei_config_read (line, sizeof (line), fp);
1468 	   linenumber++)
1469 	{
1470 	  DBG (DBG_proc,
1471 	       ">> parse_configuration_file: parsing config line \"%s\"\n",
1472 	       line);
1473 	  if (line[0] == '#')
1474 	    continue;		/* ignore line comments */
1475 	  for (s = line; isspace (*s); ++s);	/* skip white space: */
1476 	  for (t = s; *t != '\0'; t++);
1477 	  for (--t; t > s && isspace (*t); t--);
1478 	  *(++t) = '\0';	/*trim trailing space */
1479 	  if (!strlen (s))
1480 	    continue;		/* ignore empty lines */
1481 	  if ((t = strstr (s, "scsi ")) != NULL)
1482 	    {
1483 	      /*  scsi VENDOR MODEL TYPE BUS CHANNEL ID LUN */
1484 	      DBG (DBG_proc,
1485 		   ">> parse_configuration_file: config file line %d: trying to attach SCSI: %s'\n",
1486 		   linenumber, line);
1487 	      sanei_config_attach_matching_devices (t, attach_one_scsi);
1488 	    }
1489 	  else if ((t = strstr (s, "/dev/")) != NULL)
1490 	    {
1491 	      /* /dev/scanner /dev/sg0 */
1492 	      DBG (DBG_proc,
1493 		   ">> parse_configuration_file: config file line %d: trying to attach SCSI: %s'\n",
1494 		   linenumber, line);
1495 	      sanei_config_attach_matching_devices (t, attach_one_scsi);
1496 	    }
1497 	  else if ((t = strstr (s, "option")) != NULL)
1498 	    {
1499 	      for (t += 6; isspace (*t); t++);	/* skip to flag */
1500 	      /* if(strstr(t,"FLAG_VALUE")!=NULL) FLAG_VALUE=SANE_TRUE; */
1501 	    }
1502 	  else
1503 	    {
1504 	      DBG (DBG_proc,
1505 		   ">> parse_configuration_file: config file line %d: OBSOLETE !! use the scsi keyword!\n",
1506 		   linenumber);
1507 	      DBG (DBG_proc,
1508 		   ">> parse_configuration_file:   (see man sane-avision for details): trying to attach SCSI: %s'\n",
1509 		   line);
1510 	    }
1511 	}
1512       fclose (fp);
1513     }
1514   DBG (DBG_proc, "<< parse_configuration_file\n");
1515   return;
1516 }
1517 
1518 static SANE_Status
do_cancel(HS2P_Scanner * s)1519 do_cancel (HS2P_Scanner * s)
1520 {
1521   SANE_Status status;
1522   DBG (DBG_sane_proc, ">> do_cancel\n");
1523 
1524   DBG (DBG_proc, "cancel: sending OBJECT POSITION\n");
1525 
1526   s->scanning = SANE_FALSE;
1527   s->cancelled = SANE_TRUE;
1528   s->EOM = SANE_FALSE;
1529 
1530   if (s->fd >= 0)
1531     {
1532       if ((status =
1533 	   object_position (s->fd,
1534 			    OBJECT_POSITION_UNLOAD)) != SANE_STATUS_GOOD)
1535 	{
1536 	  DBG (DBG_error, "cancel: OBJECT POSITION failed\n");
1537 	}
1538       sanei_scsi_req_flush_all ();
1539       release_unit (s->fd);
1540       sanei_scsi_close (s->fd);
1541       s->fd = -1;
1542     }
1543   /*
1544      if (s->reader_pid > 0){
1545      int exit_status;
1546      sanei_thread_kill (s->reader_pid);
1547      sanei_thread_waitpid (s->reader_pid, &exit_status);
1548      s->reader_pid = 0;
1549      }
1550    */
1551 
1552   DBG (DBG_sane_proc, "<< do_cancel\n");
1553   return (SANE_STATUS_CANCELLED);
1554 }
1555 
1556 
1557 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback __sane_unused__ authorize)1558 sane_init (SANE_Int * version_code,
1559 	   SANE_Auth_Callback __sane_unused__ authorize)
1560 {
1561   FILE *fp;
1562 
1563   DBG_INIT ();			/* initialize SANE DEBUG */
1564 
1565   /*DBG (DBG_sane_init, "> sane_init (authorize = %p)\n", (void *) authorize); */
1566 #if defined PACKAGE && defined VERSION
1567   DBG (DBG_sane_init, "> sane_init: hs2p backend version %d.%d-%d ("
1568        PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD);
1569 #endif
1570   /*
1571      sanei_thread_init ();
1572    */
1573 
1574   if (version_code)
1575     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0);
1576 
1577 
1578   if ((fp = sanei_config_open (HS2P_CONFIG_FILE)) != NULL)
1579     {
1580       parse_configuration_file (fp);
1581     }
1582   else
1583     {
1584       DBG (DBG_sane_init, "> sane_init: No config file \"%s\" present!\n",
1585 	   HS2P_CONFIG_FILE);
1586     }
1587 
1588 #if 0
1589   /* avision.c: search for all supported scanners on all scsi buses & channels */
1590   for (hw = &HS2P_Device_List[0]; hw->mfg != NULL; hw++)
1591     {
1592       sanei_scsi_find_devices (hw->mfg,	/*vendor */
1593 			       hw->model,	/*model */
1594 			       NULL,	/*all types */
1595 			       -1,	/*all bus */
1596 			       -1,	/*all channel */
1597 			       -1,	/*all id */
1598 			       -1,	/*all lun */
1599 			       attach_one_scsi);	/*callback */
1600       DBG (2, "sane_init: %s %s\n", hw->mfg, hw->model);
1601     }
1602 #endif
1603 
1604   DBG (DBG_sane_init, "< sane_init\n");
1605   return SANE_STATUS_GOOD;
1606 }
1607 
1608 void
sane_exit(void)1609 sane_exit (void)
1610 {
1611   HS2P_Device *dev, *next;
1612   DBG (DBG_proc, ">> sane_exit\n");
1613 
1614   for (dev = first_dev; dev; dev = next)
1615     {
1616       next = dev->next;
1617       free ((void *) (SANE_String_Const *) dev->sane.name);
1618       free ((SANE_String_Const *) dev->sane.model);
1619       free (dev);
1620     }
1621 
1622   DBG (DBG_proc, "<< sane_exit\n");
1623 }
1624 
1625 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1626 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1627 {
1628   static const SANE_Device **devlist = 0;
1629   HS2P_Device *dev;
1630   int i;
1631   DBG (DBG_proc, ">> sane_get_devices (local_only = %d)\n", local_only);
1632 
1633   if (devlist)
1634     free (devlist);
1635   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
1636   if (!devlist)
1637     return (SANE_STATUS_NO_MEM);
1638 
1639   i = 0;
1640   for (dev = first_dev; dev; dev = dev->next)
1641     devlist[i++] = &dev->sane;
1642   devlist[i++] = 0;
1643 
1644   *device_list = devlist;
1645 
1646   DBG (DBG_proc, "<< sane_get_devices\n");
1647   return SANE_STATUS_GOOD;
1648 }
1649 
1650 SANE_Status
sane_open(SANE_String_Const devnam,SANE_Handle * handle)1651 sane_open (SANE_String_Const devnam, SANE_Handle * handle)
1652 {
1653   SANE_Status status;
1654   HS2P_Device *dev;
1655   HS2P_Scanner *s;
1656   DBG (DBG_proc, "> sane_open\n");
1657 
1658   if (devnam[0] == '\0')
1659     {
1660       for (dev = first_dev; dev; dev = dev->next)
1661 	{
1662 	  if (strcmp (dev->sane.name, devnam) == 0)
1663 	    break;
1664 	}
1665       if (!dev)
1666 	{
1667 	  status = attach (devnam, CONNECTION_SCSI, &dev);
1668 	  if (status != SANE_STATUS_GOOD)
1669 	    return (status);
1670 	}
1671     }
1672   else
1673     {
1674       dev = first_dev;
1675     }
1676   if (!dev)
1677     return (SANE_STATUS_INVAL);
1678 
1679   s = malloc (sizeof (*s));
1680   if (!s)
1681     return SANE_STATUS_NO_MEM;
1682   memset (s, 0, sizeof (*s));	/* initialize */
1683 
1684   s->fd = -1;
1685   s->hw = dev;
1686   s->hw->info.bmu = s->bmu = MILLIMETERS;	/* 01H */
1687   s->hw->info.mud = s->mud = 1;	/* If the scale is MM or POINT, mud is fixed to 1 */
1688   s->bpp = 1;			/* supports 1,4,6,8 so we set to LINEART 1bpp     */
1689   /*
1690      s->scanning  = SANE_FALSE;
1691      s->cancelled =  SANE_FALSE;
1692    */
1693   /*
1694    */
1695 
1696   ScannerDump (s);
1697   init_options (s);
1698 
1699   s->next = first_handle;	/* insert newly opened handle into list of open handles: */
1700   first_handle = s;
1701 
1702   /* initialize our parameters here AND in sane_start?
1703      get_parameters(s, 0);
1704    */
1705 
1706   *handle = s;
1707 
1708   DBG (DBG_proc, "< sane_open\n");
1709   return SANE_STATUS_GOOD;
1710 }
1711 
1712 void
sane_close(SANE_Handle handle)1713 sane_close (SANE_Handle handle)
1714 {
1715   HS2P_Scanner *s = (HS2P_Scanner *) handle;
1716   char **str;
1717   DBG (DBG_proc, ">> sane_close\n");
1718 
1719   if (s->fd != -1)
1720     sanei_scsi_close (s->fd);
1721   free (s);
1722 
1723   for (str = &compression_list[0]; *str; str++);
1724   free (*str);
1725   for (str = &scan_mode_list[0]; *str; str++);
1726   free (*str);
1727 
1728   DBG (DBG_proc, "<< sane_close\n");
1729 }
1730 
1731 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1732 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1733 {
1734   HS2P_Scanner *s = handle;
1735   DBG (DBG_proc, ">> sane_get_option_descriptor: %d name=%s\n", option,
1736        s->opt[option].name);
1737 
1738   if ((unsigned) option >= NUM_OPTIONS)
1739     return (0);
1740 
1741   DBG (DBG_info, "<< sane_get_option_descriptor: name=%s\n",
1742        s->opt[option].name);
1743   return (s->opt + option);
1744 }
1745 
1746 #if 0
1747 static SANE_Int
1748 get_scan_mode_id (char *s)	/* sequential search */
1749 {
1750   SANE_Int i;
1751 
1752   for (i = 0; scan_mode_list[i]; i++)
1753     if (strcmp (s, scan_mode_list[i]) == 0)
1754       break;
1755 
1756   /* unknown strings are treated as 'lineart' */
1757   return scan_mode_list[i] ? i : 0;
1758 }
1759 #endif
1760 static SANE_Status
update_hs2p_data(HS2P_Scanner * s)1761 update_hs2p_data (HS2P_Scanner * s)
1762 {
1763 
1764   DBG (DBG_proc, ">> update_hs2p_data\n");
1765   /* OPT_NREGX_ADF: */
1766   DBG (DBG_sane_option, "OPT_NREGX_ADF\n");
1767   s->val[OPT_NREGX_ADF].w = (SANE_Word) s->data.maintenance.nregx_adf;
1768 
1769   /* OPT_NREGY_ADF: */
1770   DBG (DBG_sane_option, "OPT_NREGY_ADF\n");
1771   s->val[OPT_NREGY_ADF].w = (SANE_Word) s->data.maintenance.nregx_book;
1772 
1773   /* OPT_NREGX_BOOK: */
1774   DBG (DBG_sane_option, "OPT_NREGX_BOOK\n");
1775   s->val[OPT_NREGX_BOOK].w = (SANE_Word) s->data.maintenance.nregx_book;
1776 
1777   /* OPT_NREGY_BOOK: */
1778   DBG (DBG_sane_option, "OPT_NREGY_BOOK\n");
1779   s->val[OPT_NREGY_BOOK].w = (SANE_Word) s->data.maintenance.nregy_book;
1780 
1781   /* OPT_NSCANS_ADF: */
1782   DBG (DBG_sane_option, "OPT_NSCANS_ADF\n");
1783   s->val[OPT_NSCANS_ADF].w =
1784     (SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0]));
1785 
1786   /* OPT_NSCANS_BOOK: */
1787   DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n");
1788   s->val[OPT_NSCANS_BOOK].w =
1789     (SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0]));
1790 
1791   /* OPT_LAMP_TIME: */
1792   DBG (DBG_sane_option, "OPT_LAMP_TIME\n");
1793   s->val[OPT_LAMP_TIME].w =
1794     (SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0]));
1795 
1796   /* OPT_EO_ODD: */
1797   DBG (DBG_sane_option, "OPT_EO_ODD\n");
1798   s->val[OPT_EO_ODD].w = (SANE_Word) s->data.maintenance.eo_odd;
1799 
1800   /* OPT_EO_EVEN: */
1801   DBG (DBG_sane_option, "OPT_EO_EVEN\n");
1802   s->val[OPT_EO_EVEN].w = (SANE_Word) s->data.maintenance.eo_even;
1803 
1804   /* OPT_BLACK_LEVEL_ODD: */
1805   DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n");
1806   s->val[OPT_BLACK_LEVEL_ODD].w =
1807     (SANE_Word) s->data.maintenance.black_level_odd;
1808 
1809   /* OPT_BLACK_LEVEL_EVEN: */
1810   DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n");
1811   s->val[OPT_BLACK_LEVEL_EVEN].w =
1812     (SANE_Word) s->data.maintenance.black_level_even;
1813 
1814   /* OPT_WHITE_LEVEL_ODD: */
1815   DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n");
1816   s->val[OPT_WHITE_LEVEL_ODD].w =
1817     (SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0]));
1818 
1819   /* OPT_WHITE_LEVEL_EVEN: */
1820   DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n");
1821   s->val[OPT_WHITE_LEVEL_EVEN].w =
1822     (SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0]));
1823 
1824   /* OPT_FIRST_ADJ_WHITE_ODD: */
1825   DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n");
1826   s->val[OPT_FIRST_ADJ_WHITE_ODD].w =
1827     (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_odd[0]));
1828 
1829   /* OPT_FIRST_ADJ_WHITE_EVEN: */
1830   DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n");
1831   s->val[OPT_FIRST_ADJ_WHITE_EVEN].w =
1832     (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_even[0]));
1833 
1834   /* OPT_DENSITY: */
1835   DBG (DBG_sane_option, "OPT_DENSITY\n");
1836   s->val[OPT_DENSITY].w = (SANE_Word) s->data.maintenance.density_adj;
1837 
1838   /* OPT_NREGX_REVERSE: */
1839   DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n");
1840   s->val[OPT_NREGX_REVERSE].w = (SANE_Word) s->data.maintenance.nregx_reverse;
1841 
1842   /* OPT_NREGY_REVERSE: */
1843   DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n");
1844   s->val[OPT_NREGY_REVERSE].w = (SANE_Word) s->data.maintenance.nregy_reverse;
1845 
1846   /* OPT_NSCANS_REVERSE_ADF: */
1847   DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n");
1848   s->val[OPT_NSCANS_REVERSE_ADF].w =
1849     (SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0]));
1850 
1851   /* OPT_REVERSE_TIME: */
1852   DBG (DBG_sane_option, "OPT_REVERSE_TIME\n");
1853   s->val[OPT_REVERSE_TIME].w =
1854     (SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0]));
1855 
1856   /* OPT_NCHARS: */
1857   DBG (DBG_sane_option, "OPT_NCHARS\n");
1858   s->val[OPT_NCHARS].w =
1859     (SANE_Word) _4btol (&(s->data.maintenance.nchars[0]));
1860 
1861   DBG (DBG_proc, "<< update_hs2p_data\n");
1862   return SANE_STATUS_GOOD;
1863 }
1864 
1865 static SANE_Status
hs2p_open(HS2P_Scanner * s)1866 hs2p_open (HS2P_Scanner * s)
1867 {
1868   SANE_Status status;
1869   DBG (DBG_proc, ">> hs2p_open\n");
1870   DBG (DBG_info, ">> hs2p_open: trying to open: name=\"%s\" fd=%d\n",
1871        s->hw->sane.name, s->fd);
1872   if ((status =
1873        sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler,
1874 			&(s->hw->sense_data))) != SANE_STATUS_GOOD)
1875     {
1876       DBG (DBG_error, "sane_start: open of %s failed: %d %s\n",
1877 	   s->hw->sane.name, status, sane_strstatus (status));
1878       return (status);
1879     }
1880   DBG (DBG_info, ">>hs2p_open: OPENED \"%s\" fd=%d\n", s->hw->sane.name,
1881        s->fd);
1882 
1883   if ((status = test_unit_ready (s->fd)) != SANE_STATUS_GOOD)
1884     {
1885       DBG (DBG_error, "hs2p_open: test_unit_ready() failed: %s\n",
1886 	   sane_strstatus (status));
1887       sanei_scsi_close (s->fd);
1888       s->fd = -1;
1889       return status;
1890     }
1891   DBG (DBG_proc, "<< hs2p_open\n");
1892   return SANE_STATUS_GOOD;
1893 }
1894 
1895 static SANE_Status
hs2p_close(HS2P_Scanner * s)1896 hs2p_close (HS2P_Scanner * s)
1897 {
1898 
1899   DBG (DBG_proc, ">> hs2p_close\n");
1900 
1901   release_unit (s->fd);
1902   sanei_scsi_close (s->fd);
1903   s->fd = -1;
1904 
1905   DBG (DBG_proc, "<< hs2p_close\n");
1906   return SANE_STATUS_GOOD;
1907 }
1908 
1909 #include <stdarg.h>
1910 static SANE_Status
get_hs2p_data(HS2P_Scanner * s,...)1911 get_hs2p_data (HS2P_Scanner * s, ...)
1912 {
1913   SANE_Status status;
1914   SANE_Byte *buf;
1915   size_t *len = &(s->data.bufsize);
1916   int dtc, fd = s->fd;
1917   u_long dtq = 0;		/* two bytes */
1918   va_list ap;
1919 
1920   DBG (DBG_proc, ">> get_hs2p_data\n");
1921   if (fd < 0)
1922     {
1923       status = hs2p_open (s);
1924       if (status != SANE_STATUS_GOOD)
1925 	{
1926 	  DBG (DBG_error, "get_hs2p_data: error opening scanner: %s\n",
1927 	       sane_strstatus (status));
1928 	  return status;
1929 	}
1930     }
1931 
1932   for (va_start (ap, s), dtc = va_arg (ap, int); dtc != DATA_TYPE_EOL;
1933        dtc = va_arg (ap, int))
1934     {
1935       DBG (DBG_proc, ">> get_hs2p_data 0x%2.2x\n", (int) dtc);
1936       switch (dtc)
1937 	{
1938 	case DATA_TYPE_GAMMA:
1939 	  buf = &(s->data.gamma[0]);
1940 	  *len = sizeof (s->data.gamma);
1941 	  break;
1942 	case DATA_TYPE_ENDORSER:
1943 	  buf = &(s->data.endorser[0]);
1944 	  *len = sizeof (s->data.endorser);
1945 	  break;
1946 	case DATA_TYPE_SIZE:
1947 	  buf = &(s->data.size);
1948 	  *len = sizeof (s->data.size);
1949 	  break;
1950 	case DATA_TYPE_PAGE_LEN:
1951 	  buf = s->data.nlines;
1952 	  *len = sizeof (s->data.nlines);
1953 	  break;
1954 	case DATA_TYPE_MAINTENANCE:
1955 	  buf = (SANE_Byte *) & (s->data.maintenance);
1956 	  *len = sizeof (s->data.maintenance);
1957 	  break;
1958 	case DATA_TYPE_ADF_STATUS:
1959 	  buf = &(s->data.adf_status);
1960 	  *len = sizeof (s->data.adf_status);
1961 	  break;
1962 	case DATA_TYPE_IMAGE:
1963 	case DATA_TYPE_HALFTONE:
1964 	default:
1965 	  DBG (DBG_info, "Data Type Code %2.2x not handled.\n", dtc);
1966 	  return SANE_STATUS_INVAL;
1967 	}
1968       DBG (DBG_info,
1969 	   "get_hs2p_data calling read_data for dtc=%2.2x and bufsize=%lu\n",
1970 	   (int) dtc, (u_long) * len);
1971       status = read_data (s->fd, buf, len, (SANE_Byte) dtc, dtq);
1972       if (status != SANE_STATUS_GOOD)
1973 	{
1974 	  DBG (DBG_error, "get_scanner_data: ERROR %s\n",
1975 	       sane_strstatus (status));
1976 	}
1977     }
1978   va_end (ap);
1979 
1980   if (fd < 0)
1981     {				/* need to return fd to original state */
1982       status = hs2p_close (s);
1983       if (status != SANE_STATUS_GOOD)
1984 	{
1985 	  DBG (DBG_error, "get_hs2p_data: error closing fd: %s\n",
1986 	       sane_strstatus (status));
1987 	}
1988     }
1989   DBG (DBG_proc, "<< get_hs2p_data: %d\n", status);
1990   return (status);
1991 }
1992 
1993 static SANE_Status
print_maintenance_data(MAINTENANCE_DATA * d)1994 print_maintenance_data (MAINTENANCE_DATA * d)
1995 {
1996   DBG (DBG_proc, ">> print_maintenance_data: \n");
1997 
1998   DBG (DBG_LEVEL, "nregx_adf = %d\n", d->nregx_adf);
1999   DBG (DBG_LEVEL, "nregy_adf = %d\n", d->nregy_adf);
2000 
2001   DBG (DBG_LEVEL, "nregx_book = %d\n", d->nregx_book);
2002   DBG (DBG_LEVEL, "nregy_book = %d\n", d->nregy_book);
2003 
2004   DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0])));
2005   DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0])));
2006 
2007   DBG (DBG_LEVEL, "lamp time = %lu\n", _4btol (&(d->lamp_time[0])));
2008 
2009   DBG (DBG_LEVEL, "eo_odd = %d\n", d->eo_odd);
2010   DBG (DBG_LEVEL, "eo_even = %d\n", d->eo_even);
2011 
2012   DBG (DBG_LEVEL, "black_level_odd = %d\n", d->black_level_odd);
2013   DBG (DBG_LEVEL, "black_level_even = %d\n", d->black_level_even);
2014 
2015   DBG (DBG_LEVEL, "white_level_odd = %lu\n",
2016        _2btol (&(d->white_level_odd[0])));
2017   DBG (DBG_LEVEL, "white_level_even = %lu\n",
2018        _2btol (&(d->white_level_even[0])));
2019 
2020   DBG (DBG_LEVEL, "first_adj_white_odd = %lu\n",
2021        _2btol (&(d->first_adj_white_odd[0])));
2022   DBG (DBG_LEVEL, "first_adj_white_even = %lu\n",
2023        _2btol (&(d->first_adj_white_even[0])));
2024 
2025   DBG (DBG_LEVEL, "density_adj = %d\n", d->density_adj);
2026 
2027   DBG (DBG_LEVEL, "nregx_reverse = %d\n", d->nregx_reverse);
2028   DBG (DBG_LEVEL, "nregy_reverse = %d\n", d->nregy_reverse);
2029 
2030   DBG (DBG_LEVEL, "nscans_reverse_adf = %lu\n",
2031        _4btol (&(d->nscans_reverse_adf[0])));
2032 
2033   DBG (DBG_LEVEL, "reverse_time = %lu\n", _4btol (&(d->reverse_time[0])));
2034 
2035   DBG (DBG_LEVEL, "nchars = %lu\n", _4btol (&(d->nchars[0])));
2036 
2037   DBG (DBG_proc, "<< print_maintenance_data: \n");
2038   return SANE_STATUS_GOOD;
2039 }
2040 
2041 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)2042 sane_control_option (SANE_Handle handle, SANE_Int option,
2043 		     SANE_Action action, void *val, SANE_Int * info)
2044 {
2045   HS2P_Scanner *s = handle;
2046   SANE_Status status;
2047   SANE_Word cap;
2048   SANE_String_Const name;
2049   SANE_Int paper_id;
2050 
2051 
2052 
2053   name = s->opt[option].name ? s->opt[option].name : "(nil)";
2054   if (info)
2055     *info = 0;
2056   DBG (DBG_proc, ">> sane_control_option: %s option=%d name=%s\n",
2057        action == SANE_ACTION_GET_VALUE ? "SET" : "GET", option, name);
2058 
2059   if (s->scanning)
2060     return (SANE_STATUS_DEVICE_BUSY);
2061   if (option >= NUM_OPTIONS)
2062     return (SANE_STATUS_INVAL);
2063 
2064   cap = s->opt[option].cap;
2065   if (!SANE_OPTION_IS_ACTIVE (cap))
2066     return (SANE_STATUS_INVAL);
2067 
2068   if (action == SANE_ACTION_GET_VALUE)
2069     {
2070       DBG (DBG_proc, "sane_control_option get_value option=%d\n", option);
2071       switch (option)
2072 	{
2073 	  /* word options: */
2074 	case OPT_RESOLUTION:
2075 	case OPT_X_RESOLUTION:
2076 	case OPT_Y_RESOLUTION:
2077 	case OPT_TL_X:
2078 	case OPT_TL_Y:
2079 	case OPT_BR_X:
2080 	case OPT_BR_Y:
2081 	case OPT_BRIGHTNESS:
2082 	case OPT_THRESHOLD:
2083 	case OPT_CONTRAST:
2084 	case OPT_NUM_OPTS:
2085 	  *(SANE_Word *) val = s->val[option].w;
2086 	  return (SANE_STATUS_GOOD);
2087 
2088 	  /* bool options: */
2089 	  /*case OPT_AUTOBORDER: case OPT_DESKEW: case OPT_CHECK_ADF: case OPT_BATCH: */
2090 	case OPT_PREVIEW:
2091 	case OPT_SCAN_WAIT_MODE:
2092 	case OPT_DUPLEX:
2093 	case OPT_AUTO_SIZE:
2094 	case OPT_NEGATIVE:
2095 	case OPT_ENDORSER:
2096 	case OPT_SMOOTHING:
2097 	case OPT_WHITE_BALANCE:
2098 	case OPT_PREFEED:
2099 	case OPT_CUSTOM_GAMMA:
2100 	case OPT_PADDING:
2101 	  *(SANE_Bool *) val = s->val[option].w;
2102 	  return (SANE_STATUS_GOOD);
2103 
2104 	  /* string options: */
2105 	  /* case OPT_ADF:      */
2106 	  /* case OPT_BITORDER: */
2107 	  /* case OPT_ROTATION  */
2108 	  /* case OPT_SECTION:  */
2109 	case OPT_INQUIRY:
2110 	case OPT_SCAN_SOURCE:
2111 	case OPT_PAGE_ORIENTATION:
2112 	case OPT_PAPER_SIZE:
2113 	case OPT_SCAN_MODE:
2114 	case OPT_ENDORSER_STRING:
2115 	case OPT_COMPRESSION:
2116 	case OPT_NOISEREMOVAL:
2117 	case OPT_GRAYFILTER:
2118 	case OPT_HALFTONE_CODE:
2119 	case OPT_HALFTONE_PATTERN:
2120 	case OPT_GAMMA:
2121 	case OPT_AUTOSEP:
2122 	case OPT_AUTOBIN:
2123 	case OPT_PADDING_TYPE:
2124 	  DBG (DBG_proc, "STRING=%s\n", s->val[option].s);
2125 	  strcpy (val, s->val[option].s);
2126 	  return (SANE_STATUS_GOOD);
2127 	  DBG (DBG_proc, "sizeof(val)=%lu sizeof(s)=%lu\n",
2128 	       (u_long) sizeof (val), (u_long) sizeof (s->val[option].s));
2129 	  return (SANE_STATUS_GOOD);
2130 
2131 	  /* gamma */
2132 	case OPT_GAMMA_VECTOR_GRAY:
2133 	  memcpy (val, s->val[option].wa, s->opt[option].size);
2134 	  return SANE_STATUS_GOOD;
2135 
2136 	  /* MAINTENANCE DATA */
2137 	case OPT_DATA_GROUP:
2138 	case OPT_UPDATE:
2139 	  return SANE_STATUS_GOOD;
2140 	case OPT_NREGX_ADF:
2141 	  DBG (DBG_sane_option, "OPT_NREGX_ADF\n");
2142 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_adf;
2143 	  return SANE_STATUS_GOOD;
2144 	case OPT_NREGY_ADF:
2145 	  DBG (DBG_sane_option, "OPT_NREGY_ADF\n");
2146 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book;
2147 	  return SANE_STATUS_GOOD;
2148 	case OPT_NREGX_BOOK:
2149 	  DBG (DBG_sane_option, "OPT_NREGX_BOOK\n");
2150 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book;
2151 	  return SANE_STATUS_GOOD;
2152 	case OPT_NREGY_BOOK:
2153 	  DBG (DBG_sane_option, "OPT_NREGY_BOOK\n");
2154 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_book;
2155 	  return SANE_STATUS_GOOD;
2156 	case OPT_NSCANS_ADF:
2157 	  DBG (DBG_sane_option, "OPT_NSCANS_ADF\n");
2158 	  *(SANE_Word *) val =
2159 	    (SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0]));
2160 	  return SANE_STATUS_GOOD;
2161 	case OPT_NSCANS_BOOK:
2162 	  DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n");
2163 	  *(SANE_Word *) val =
2164 	    (SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0]));
2165 	  return SANE_STATUS_GOOD;
2166 	case OPT_LAMP_TIME:
2167 	  DBG (DBG_sane_option, "OPT_LAMP_TIME\n");
2168 	  *(SANE_Word *) val =
2169 	    (SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0]));
2170 	  return SANE_STATUS_GOOD;
2171 	case OPT_EO_ODD:
2172 	  DBG (DBG_sane_option, "OPT_EO_ODD\n");
2173 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_odd;
2174 	  return SANE_STATUS_GOOD;
2175 	case OPT_EO_EVEN:
2176 	  DBG (DBG_sane_option, "OPT_EO_EVEN\n");
2177 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_even;
2178 	  return SANE_STATUS_GOOD;
2179 	case OPT_BLACK_LEVEL_ODD:
2180 	  DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n");
2181 	  *(SANE_Word *) val =
2182 	    (SANE_Word) s->data.maintenance.black_level_odd;
2183 	  return SANE_STATUS_GOOD;
2184 	case OPT_BLACK_LEVEL_EVEN:
2185 	  DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n");
2186 	  *(SANE_Word *) val =
2187 	    (SANE_Word) s->data.maintenance.black_level_even;
2188 	  return SANE_STATUS_GOOD;
2189 	case OPT_WHITE_LEVEL_ODD:
2190 	  DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n");
2191 	  *(SANE_Word *) val =
2192 	    (SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0]));
2193 	  return SANE_STATUS_GOOD;
2194 	case OPT_WHITE_LEVEL_EVEN:
2195 	  DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n");
2196 	  *(SANE_Word *) val =
2197 	    (SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0]));
2198 	  return SANE_STATUS_GOOD;
2199 	case OPT_FIRST_ADJ_WHITE_ODD:
2200 	  DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n");
2201 	  *(SANE_Word *) val =
2202 	    (SANE_Word)
2203 	    _2btol (&(s->data.maintenance.first_adj_white_odd[0]));
2204 	  return SANE_STATUS_GOOD;
2205 	case OPT_FIRST_ADJ_WHITE_EVEN:
2206 	  DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n");
2207 	  *(SANE_Word *) val =
2208 	    (SANE_Word)
2209 	    _2btol (&(s->data.maintenance.first_adj_white_even[0]));
2210 	  return SANE_STATUS_GOOD;
2211 	case OPT_DENSITY:
2212 	  DBG (DBG_sane_option, "OPT_DENSITY\n");
2213 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.density_adj;
2214 	  return SANE_STATUS_GOOD;
2215 	case OPT_NREGX_REVERSE:
2216 	  DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n");
2217 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_reverse;
2218 	  return SANE_STATUS_GOOD;
2219 	case OPT_NREGY_REVERSE:
2220 	  DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n");
2221 	  *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_reverse;
2222 	  return SANE_STATUS_GOOD;
2223 	case OPT_NSCANS_REVERSE_ADF:
2224 	  DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n");
2225 	  *(SANE_Word *) val =
2226 	    (SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0]));
2227 	  return SANE_STATUS_GOOD;
2228 	case OPT_REVERSE_TIME:
2229 	  DBG (DBG_sane_option, "OPT_REVERSE_TIME\n");
2230 	  *(SANE_Word *) val =
2231 	    (SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0]));
2232 	  return SANE_STATUS_GOOD;
2233 	case OPT_NCHARS:
2234 	  DBG (DBG_sane_option, "OPT_NCHARS\n");
2235 	  *(SANE_Word *) val =
2236 	    (SANE_Word) _4btol (&(s->data.maintenance.nchars[0]));
2237 	  return (SANE_STATUS_GOOD);
2238 
2239 	default:
2240 	  DBG (DBG_proc, "sane_control_option:invalid option number %d\n",
2241 	       option);
2242 	  return SANE_STATUS_INVAL;
2243 	}
2244     }
2245   else if (action == SANE_ACTION_SET_VALUE)
2246     {
2247       DBG (DBG_proc, "sane_control_option set_value\n");
2248       switch (s->opt[option].type)
2249 	{
2250 	case SANE_TYPE_BOOL:
2251 	case SANE_TYPE_INT:
2252 	  DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %d\n",
2253 	       name, option, *(SANE_Word *) val);
2254 	  break;
2255 	case SANE_TYPE_FIXED:
2256 	  DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %f\n",
2257 	       name, option, SANE_UNFIX (*(SANE_Word *) val));
2258 	  break;
2259 	case SANE_TYPE_STRING:
2260 	  DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %s\n",
2261 	       name, option, (char *) val);
2262 	  break;
2263 	case SANE_TYPE_BUTTON:
2264 	  DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n",
2265 	       name, option);
2266 	  update_hs2p_data (s);
2267 	  break;
2268 	default:
2269 	  DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n", name,
2270 	       option);
2271 	}
2272 
2273       if (!SANE_OPTION_IS_SETTABLE (cap))
2274 	return (SANE_STATUS_INVAL);
2275       if ((status =
2276 	   sanei_constrain_value (s->opt + option, val,
2277 				  info)) != SANE_STATUS_GOOD)
2278 	return status;
2279 
2280       switch (option)
2281 	{
2282 	  /* (mostly) side-effect-free word options: */
2283 	case OPT_TL_X:
2284 	case OPT_TL_Y:
2285 	case OPT_BR_X:
2286 	case OPT_BR_Y:
2287 	  s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE;	/* disable auto size */
2288 	  /* make sure that paper-size is set to custom */
2289 	  if (info && s->val[option].w != *(SANE_Word *) val)
2290 	    *info |= SANE_INFO_RELOAD_PARAMS;
2291 	  s->val[option].w = *(SANE_Word *) val;
2292 	  /* resets the paper format to user defined */
2293 	  if (strcmp (s->val[OPT_PAPER_SIZE].s, paper_list[0]) != 0)	/* CUSTOM PAPER SIZE */
2294 	    {
2295 	      if (info)
2296 		*info |= SANE_INFO_RELOAD_OPTIONS;
2297 	      if (s->val[OPT_PAPER_SIZE].s)
2298 		free (s->val[OPT_PAPER_SIZE].s);
2299 	      s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]);	/* CUSTOM PAPER SIZE */
2300 	    }
2301 	  /* fall through */
2302 	case OPT_X_RESOLUTION:
2303 	case OPT_Y_RESOLUTION:
2304 	  if (info && s->val[option].w != *(SANE_Word *) val)
2305 	    *info |= SANE_INFO_RELOAD_PARAMS;
2306 
2307 	  /* fall through */
2308 	  /*case OPT_ACE_FUNCTION: case OPT_ACE_SENSITIVITY: */
2309 	case OPT_BRIGHTNESS:
2310 	case OPT_THRESHOLD:
2311 	case OPT_CONTRAST:
2312 	case OPT_NUM_OPTS:
2313 	  s->val[option].w = *(SANE_Word *) val;
2314 	  return (SANE_STATUS_GOOD);
2315 
2316 	  /* string options */
2317 	case OPT_NOISEREMOVAL:
2318 	case OPT_AUTOSEP:
2319 	case OPT_AUTOBIN:
2320 	case OPT_COMPRESSION:
2321 	case OPT_PADDING_TYPE:
2322 	case OPT_GRAYFILTER:
2323 	case OPT_HALFTONE_CODE:
2324 	case OPT_HALFTONE_PATTERN:
2325 	case OPT_ENDORSER_STRING:
2326 	  if (s->val[option].s)
2327 	    free (s->val[option].s);
2328 	  s->val[option].s = strdup (val);
2329 	  return SANE_STATUS_GOOD;
2330 
2331 	  /* boolean options: */
2332 	case OPT_PREVIEW:
2333 	case OPT_DUPLEX:
2334 	case OPT_NEGATIVE:
2335 	case OPT_SCAN_WAIT_MODE:
2336 	case OPT_ENDORSER:
2337 	case OPT_SMOOTHING:
2338 	case OPT_WHITE_BALANCE:
2339 	case OPT_PREFEED:
2340 	case OPT_PADDING:
2341 	  s->val[option].w = *(SANE_Word *) val;
2342 	  return SANE_STATUS_GOOD;
2343 
2344 	case OPT_GAMMA_VECTOR_GRAY:
2345 	  memcpy (s->val[option].wa, val, s->opt[option].size);
2346 	  return SANE_STATUS_GOOD;
2347 
2348 	  /* options with side effect */
2349 	case OPT_GAMMA:
2350 	  if (strcmp (s->val[option].s, (SANE_String) val))
2351 	    {
2352 	      if (!strcmp ((SANE_String) val, "User"))
2353 		{
2354 		  s->val[OPT_CUSTOM_GAMMA].b = SANE_TRUE;
2355 		  s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
2356 		  /* Brightness and Contrast do not work when downloading Gamma Table */
2357 		  s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2358 		  s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
2359 		}
2360 	      else
2361 		{
2362 		  s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE;
2363 		  s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
2364 		  s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
2365 		  s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
2366 		}
2367 	      if (info)
2368 		*info |= SANE_INFO_RELOAD_OPTIONS;
2369 	    }
2370 	  if (s->val[option].s)
2371 	    free (s->val[option].s);
2372 	  s->val[option].s = strdup (val);
2373 	  return SANE_STATUS_GOOD;
2374 
2375 	case OPT_CUSTOM_GAMMA:
2376 	  s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val;
2377 	  if (s->val[OPT_CUSTOM_GAMMA].w)
2378 	    {
2379 	      s->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE;
2380 	    }
2381 	  else
2382 	    {
2383 	      s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE;
2384 	    }
2385 	  if (info)
2386 	    *info |= SANE_INFO_RELOAD_OPTIONS;
2387 	  return SANE_STATUS_GOOD;
2388 
2389 	case OPT_RESOLUTION:
2390 	  if (info && s->val[option].w != *(SANE_Word *) val)
2391 	    *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2392 	  s->val[option].w = *(SANE_Word *) val;
2393 	  s->val[OPT_X_RESOLUTION].w = *(SANE_Word *) val;
2394 	  s->val[OPT_Y_RESOLUTION].w = *(SANE_Word *) val;
2395 	  return SANE_STATUS_GOOD;
2396 	case OPT_SCAN_SOURCE:
2397 	  /* a string option */
2398 	  /*    Since the scanner ejects the sheet in ADF mode
2399 	   * it is impossible to scan multiple sections in one document
2400 	   *    In ADF mode, because of mechanical limitations:
2401 	   * the minimum document size is (x,y)=(69mm x 120mm)
2402 	   */
2403 	  if (info && strcmp ((char *) s->val[option].s, (char *) val))
2404 	    *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2405 	  if (s->val[option].s)
2406 	    free (s->val[option].s);
2407 	  s->val[option].s = strdup (val);
2408 	  if (!strcmp ("ADF", (SANE_String) val))
2409 	    {
2410 	      s->opt[OPT_ENDORSER].cap &= ~SANE_CAP_INACTIVE;
2411 	      s->opt[OPT_ENDORSER_STRING].cap &= ~SANE_CAP_INACTIVE;
2412 	      s->opt[OPT_PREFEED].cap &= ~SANE_CAP_INACTIVE;
2413 	      s->opt[OPT_DUPLEX].cap &= ~SANE_CAP_INACTIVE;
2414 	      /*s->opt[OPT_PADDING].cap &= ~SANE_CAP_INACTIVE; */
2415 	    }
2416 	  else
2417 	    {			/* Flatbed */
2418 	      s->opt[OPT_ENDORSER].cap |= SANE_CAP_INACTIVE;
2419 	      s->opt[OPT_ENDORSER_STRING].cap |= SANE_CAP_INACTIVE;
2420 	      s->opt[OPT_PREFEED].cap |= SANE_CAP_INACTIVE;
2421 	      s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE;
2422 	      s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE;
2423 	    }
2424 	  return SANE_STATUS_GOOD;
2425 	case OPT_SCAN_MODE:
2426 	  /* a string option */
2427 	  /* scan mode != lineart disables compression, setting it to  'none' */
2428 	  if (strcmp (s->val[option].s, (SANE_String) val))
2429 	    {
2430 	      if (info)
2431 		*info |= SANE_INFO_RELOAD_OPTIONS;
2432 	      if (!strcmp (SM_LINEART, (SANE_String) val))
2433 		{
2434 		  s->image_composition = LINEART;
2435 		  s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE;	/* enable compression control */
2436 		  s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;	/* enable threshold control   */
2437 		  s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;	/* disable brightness control */
2438 		  s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;	/* disable contrast control   */
2439 		  s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE;	/* disable gamma              */
2440 		  s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;	/* disable gamma              */
2441 		  s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE;	/* disable gamma              */
2442 		  s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE;	/* disable halftone code      */
2443 		  s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;	/* disable halftone pattern   */
2444 		}
2445 	      else
2446 		{
2447 		  if (!strcmp (SM_HALFTONE, (SANE_String) val))
2448 		    {
2449 		      s->image_composition = HALFTONE;
2450 		      s->opt[OPT_HALFTONE_CODE].cap &= ~SANE_CAP_INACTIVE;	/* enable halftone code    */
2451 		      s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;	/* enable halftone pattern */
2452 		    }
2453 		  else if (!strcmp (SM_4BITGRAY, (SANE_String) val) ||
2454 			   !strcmp (SM_6BITGRAY, (SANE_String) val) ||
2455 			   !strcmp (SM_8BITGRAY, (SANE_String) val))
2456 		    {
2457 		      s->image_composition = GRAYSCALE;
2458 		      s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE;	/* enable  gamma            */
2459 		      s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;	/* enable  brightness       */
2460 		      s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;	/* enable  contrast         */
2461 		      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;	/* disable threshold        */
2462 		      s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE;	/* disable compression      */
2463 		      s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE;	/* disable halftone code    */
2464 		      s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;	/* disable halftone pattern */
2465 		      if (s->val[OPT_COMPRESSION].s
2466 			  && get_compression_id (s->val[OPT_COMPRESSION].s) !=
2467 			  0)
2468 			{
2469 			  free (s->val[OPT_COMPRESSION].s);
2470 			  s->val[OPT_COMPRESSION].s =
2471 			    strdup (compression_list[0]);
2472 			}
2473 		    }
2474 		}
2475 	      free (s->val[option].s);
2476 	      s->val[option].s = strdup (val);
2477 	    }
2478 	  return SANE_STATUS_GOOD;
2479 
2480 	case OPT_PAGE_ORIENTATION:
2481 	  if (strcmp (s->val[option].s, (SANE_String) val))
2482 	    {
2483 	      free (s->val[option].s);
2484 	      s->val[option].s = strdup (val);
2485 	      if (info)
2486 		*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2487 	    }
2488 	  /* set val to current selected paper size */
2489 	  paper_id = get_paper_id ((SANE_String) s->val[OPT_PAPER_SIZE].s);
2490 	  goto paper_id;
2491 	case OPT_PAPER_SIZE:
2492 	  /* a string option */
2493 	  /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */
2494 	  s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE;	/* disable auto size */
2495 	  if (strcmp (s->val[option].s, (SANE_String) val))
2496 	    {
2497 	      paper_id = get_paper_id ((SANE_String) val);
2498 
2499 	      /* paper_id 0 is a special case (custom) that
2500 	       * disables the paper size control of geometry
2501 	       */
2502 	    paper_id:
2503 	      if (paper_id != 0)
2504 		{
2505 		  double x_max, y_max, x, y, temp;
2506 
2507 		  x_max = SANE_UNFIX (s->hw->info.x_range.max);
2508 		  y_max = SANE_UNFIX (s->hw->info.y_range.max);
2509 
2510 		  /* a dimension of 0.0 (or less) is replaced with the max value */
2511 		  x = (paper_sizes[paper_id].width <= 0.0) ? x_max :
2512 		    paper_sizes[paper_id].width;
2513 		  y = (paper_sizes[paper_id].length <= 0.0) ? y_max :
2514 		    paper_sizes[paper_id].length;
2515 
2516 		  if (info)
2517 		    *info |=
2518 		      SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2519 
2520 		  if (!strcmp (s->val[OPT_PAGE_ORIENTATION].s, LANDSCAPE))	/* swap */
2521 		    {
2522 		      temp = y_max;
2523 		      y_max = x_max;
2524 		      x_max = temp;
2525 		      temp = y;
2526 		      y = x;
2527 		      x = temp;
2528 		    }
2529 
2530 		  s->val[OPT_TL_X].w = SANE_FIX (0.0);
2531 		  s->val[OPT_TL_Y].w = SANE_FIX (0.0);
2532 		  s->val[OPT_BR_X].w = SANE_FIX (MIN (x, x_max));
2533 		  s->val[OPT_BR_Y].w = SANE_FIX (MIN (y, y_max));
2534 		}
2535 	      free (s->val[option].s);
2536 	      s->val[option].s = strdup (val);
2537 	    }
2538 	  return SANE_STATUS_GOOD;
2539 	case OPT_UPDATE:	/* SANE_TYPE_BUTTON */
2540 	  DBG (DBG_info,
2541 	       "OPT_UPDATE: ready to call get_hs2p_data: fd=%d\n", s->fd);
2542 	  get_hs2p_data (s,
2543 			 /* DATA_TYPE_GAMMA, */
2544 			 /* DATA_TYPE_ENDORSER, */
2545 			 /* DATA_TYPE_SIZE, */
2546 			 /* DATA_TYPE_PAGE_LEN, */
2547 			 DATA_TYPE_MAINTENANCE,
2548 			 /* DATA_TYPE_ADF_STATUS, */
2549 			 /* DATA_TYPE_IMAGE, */
2550 			 /* DATA_TYPE_HALFTONE, */
2551 			 DATA_TYPE_EOL);	/* va_list end */
2552 	  update_hs2p_data (s);
2553 	  if (DBG_LEVEL >= DBG_info)
2554 	    print_maintenance_data (&(s->data.maintenance));
2555 	  if (info)
2556 	    *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
2557 	  return SANE_STATUS_GOOD;
2558 	}
2559       return (SANE_STATUS_GOOD);
2560     }
2561 
2562   DBG (DBG_proc, "<< sane_control_option\n");
2563   return (SANE_STATUS_INVAL);
2564 
2565 }
2566 
2567 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)2568 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
2569 {
2570   HS2P_Scanner *s = handle;
2571   DBG (DBG_proc, ">> sane_get_parameters\n");
2572 
2573   if (!s->scanning)
2574     {
2575       int width, length, xres, yres;
2576       const char *mode;
2577 
2578       memset (&s->params, 0, sizeof (s->params));	/* CLEAR SANE_Parameters */
2579 
2580       width =
2581 	(int) (SANE_UNFIX (s->val[OPT_BR_X].w) -
2582 	       SANE_UNFIX (s->val[OPT_TL_X].w));
2583       length =
2584 	(int) (SANE_UNFIX (s->val[OPT_BR_Y].w) -
2585 	       SANE_UNFIX (s->val[OPT_TL_Y].w));
2586       xres = s->val[OPT_X_RESOLUTION].w;
2587       yres = s->val[OPT_Y_RESOLUTION].w;
2588       DBG (DBG_proc,
2589 	   ">>sane_get_parameters: (W/L)=(%d/%d) (xres/yres)=(%d/%d) mud=%d\n",
2590 	   width, length, xres, yres, s->hw->info.mud);
2591 
2592       /* make best-effort guess at what parameters will look like once scanning starts.  */
2593       if (xres > 0 && yres > 0 && width > 0 && length > 0)
2594 	{			/* convert from mm to pixels */
2595 	  s->params.pixels_per_line =
2596 	    width * xres / s->hw->info.mud / MM_PER_INCH;
2597 	  s->params.lines = length * yres / s->hw->info.mud / MM_PER_INCH;
2598 	}
2599 
2600       mode = s->val[OPT_SCAN_MODE].s;
2601       if ((strcmp (mode, SM_LINEART) == 0) ||
2602 	  (strcmp (mode, SM_HALFTONE)) == 0)
2603 	{
2604 	  s->params.format = SANE_FRAME_GRAY;
2605 	  s->params.bytes_per_line = s->params.pixels_per_line / 8;
2606 	  /* if the scanner truncates to the byte boundary, so: chop! */
2607 	  s->params.pixels_per_line = s->params.bytes_per_line * 8;
2608 	  s->params.depth = 1;
2609 	}
2610       else			/* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */
2611 	{
2612 	  s->params.format = SANE_FRAME_GRAY;
2613 	  s->params.bytes_per_line = s->params.pixels_per_line;
2614 	  s->params.depth = 8;
2615 	}
2616       s->params.last_frame = SANE_TRUE;
2617     }
2618   else
2619     DBG (DBG_proc, "sane_get_parameters: scanning, so can't get params\n");
2620 
2621   if (params)
2622     *params = s->params;
2623 
2624   DBG (DBG_proc,
2625        "%d pixels per line, %d bytes per line, %d lines high, total %lu bytes, "
2626        "dpi=%ld\n", s->params.pixels_per_line, s->params.bytes_per_line,
2627        s->params.lines, (u_long) s->bytes_to_read,
2628        (long) SANE_UNFIX (s->val[OPT_Y_RESOLUTION].w));
2629 
2630   DBG (DBG_proc, "<< sane_get_parameters\n");
2631   return (SANE_STATUS_GOOD);
2632 }
2633 
2634 static SANE_Status
set_window_data(HS2P_Scanner * s,SWD * wbuf)2635 set_window_data (HS2P_Scanner * s, SWD * wbuf)
2636 {
2637   struct hs2p_window_data *data;
2638   int i, nwin, id, xres, yres, xmax, ymax;
2639   long ulx, uly, width, length, number, bytes;
2640   double offset;
2641 
2642   DBG (DBG_proc, ">> set_window_data: sizeof(*wbuf)=%lu; window len=%lu\n",
2643        (u_long) sizeof (*wbuf), (u_long) sizeof (wbuf->data));
2644 
2645   /* initialize our window buffer with zeros */
2646   DBG (DBG_proc, ">> set_window_data: CLEARING wbuf\n");
2647   memset (wbuf, 0, sizeof (*wbuf));
2648 
2649   /* Header */
2650   DBG (DBG_proc,
2651        ">> set_window_data: writing Window Descriptor Length =%lu\n",
2652        (u_long) sizeof (wbuf->data));
2653   _lto2b (sizeof (wbuf->data), &wbuf->hdr.len[0]);
2654 
2655   /* X-Axis Resolution 100-800dpi in 1 dpi steps */
2656   xres = s->val[OPT_X_RESOLUTION].w;
2657   if (xres < s->hw->info.resMinX || xres > s->hw->info.resMaxX)
2658     {
2659       DBG (DBG_error, "XRESOLUTION %d IS NOT WITHIN [%d, %d]\n", xres,
2660 	   s->hw->info.resMinX, s->hw->info.resMaxX);
2661       return (SANE_STATUS_INVAL);
2662     }
2663 
2664   /* Y-Axis Resolution 100-800dpi in 1 dpi steps */
2665   yres = s->val[OPT_Y_RESOLUTION].w;
2666   if (yres < s->hw->info.resMinY || yres > s->hw->info.resMaxY)
2667     {
2668       DBG (DBG_error, "YRESOLUTION %d IS NOT WITHIN [%d, %d]\n", yres,
2669 	   s->hw->info.resMinY, s->hw->info.resMaxY);
2670       return (SANE_STATUS_INVAL);
2671     }
2672 
2673   ulx = (long) SANE_UNFIX (s->val[OPT_TL_X].w);
2674   uly = (long) SANE_UNFIX (s->val[OPT_TL_Y].w);
2675   DBG (DBG_info, "set_window_data: upperleft=(%ld,%ld)\n", ulx, uly);
2676 
2677   width = (long) SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w);	/* Window Width */
2678   length = (long) SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w);	/* Window Length */
2679   DBG (DBG_info, "set_window_data: WxL= %ld x %ld\n", width, length);
2680 
2681   /* NOTE: the width in inches converted to byte unit must be the following values or less
2682    * Binary:       620 bytes
2683    * 4-bits gray: 2480 bytes
2684    * 8-bits gray: 4960 bytes
2685    */
2686   if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_LINEART))
2687     {
2688       bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w / 8.0);
2689       if (bytes > 620)
2690 	{
2691 	  DBG (DBG_error,
2692 	       "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n",
2693 	       width, s->val[OPT_X_RESOLUTION].w, bytes);
2694 	  return (SANE_STATUS_INVAL);
2695 	}
2696     }
2697   else if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_4BITGRAY))
2698     {
2699       bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w / 2.0);
2700       if (bytes > 2480)
2701 	{
2702 	  DBG (DBG_error,
2703 	       "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n",
2704 	       width, s->val[OPT_X_RESOLUTION].w, bytes);
2705 	  return (SANE_STATUS_INVAL);
2706 	}
2707     }
2708   else if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_8BITGRAY))
2709     {
2710       bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w);
2711       if (bytes > 4960)
2712 	{
2713 	  DBG (DBG_error,
2714 	       "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n",
2715 	       width, s->val[OPT_X_RESOLUTION].w, bytes);
2716 	  return (SANE_STATUS_INVAL);
2717 	}
2718     }
2719 
2720 
2721   if (strcmp (s->val[OPT_SCAN_SOURCE].s, scan_source_list[ADF]) == 0)
2722     {
2723       offset = (SANE_UNFIX (s->hw->info.x_range.max) - width) / 2.0;
2724       DBG (DBG_info, "set_window_data: ADF origin offset=%f\n", offset);
2725 
2726       ulx += (long) offset;
2727     }
2728 
2729 
2730   if (strcmp (s->val[OPT_SCAN_SOURCE].s, scan_source_list[FB]) == 0)
2731     {				/* FB */
2732       xmax = 298;		/*mm */
2733       ymax = 432;
2734     }
2735   else
2736     {				/* ADF */
2737       xmax = 298;
2738       ymax = 2000;
2739     }
2740 
2741   /* Boundary Conditions when BMU = MM */
2742   number = ulx + width;
2743   if (number <= 0 || number > xmax)
2744     {
2745       DBG (DBG_error, "NOT WITHIN BOUNDS: ulx=%ld width=%ld sum=%ld\n",
2746 	   ulx, width, number);
2747       return (SANE_STATUS_INVAL);
2748     }
2749   number = uly + length;
2750   if (number <= 0 || number > ymax)
2751     {
2752       DBG (DBG_error, "NOT WITHIN BOUNDS: uly=%ld length=%ld sum=%ld\n",
2753 	   uly, length, number);
2754       return (SANE_STATUS_INVAL);
2755     }
2756 
2757 
2758 
2759   /* For each window (up to 2 if we're duplexing) */
2760   nwin = (s->val[OPT_DUPLEX].w == SANE_TRUE) ? 2 : 1;
2761   for (i = 0; i < nwin; i++)
2762     {
2763       data = &(wbuf->data[i]);
2764       data->window_id = i;
2765       data->auto_bit &= 0xFE;	/* Auto bit set to 0 since auto function isn't supported */
2766 
2767       _lto2b (xres, &data->xres[0]);	/* Set X resolution */
2768       _lto2b (yres, &data->yres[0]);	/* Set Y resolution */
2769 
2770       _lto4b (ulx, &data->ulx[0]);	/* X-Axis Upper Left */
2771       _lto4b (uly, &data->uly[0]);	/* Y-Axis Upper Left */
2772 
2773       _lto4b (width, &data->width[0]);	/* Window Width */
2774       _lto4b (length, &data->length[0]);	/* Window Length */
2775 
2776 
2777 
2778 
2779 
2780 
2781       data->brightness = s->val[OPT_BRIGHTNESS].w;	/* black-white: 1-255; 0 is default 128 */
2782       data->threshold = s->val[OPT_THRESHOLD].w;	/* light-dark:  1-255; 0 is default 128 */
2783       data->contrast = s->val[OPT_CONTRAST].w;	/* low-high:    1-255: 0 is default 128 */
2784       if (data->brightness == 128)
2785 	data->brightness = 0;
2786       if (data->threshold == 128)
2787 	data->threshold = 0;
2788       if (data->contrast == 128)
2789 	data->contrast = 0;
2790 
2791       data->image_composition = s->image_composition;
2792       data->bpp = s->bpp = s->params.depth;
2793 
2794       /* Byte 27, 347 Halftone Code: if HALFTONE, then either DITHER or ERROR_DIFFUSION */
2795       if (s->image_composition == HALFTONE)
2796 	{			/* Then let's use pattern selected by user */
2797 	  data->halftone_code =
2798 	    (get_halftone_code_id (s->val[OPT_HALFTONE_CODE].s) ==
2799 	     0) ? DITHER : ERROR_DIFFUSION;
2800 	  data->halftone_id =
2801 	    get_halftone_pattern_val (s->val[OPT_HALFTONE_PATTERN].s);
2802 	}
2803       else
2804 	{
2805 	  data->halftone_code = DITHER;	/* 00H reserved */
2806 	  data->halftone_id = 0x01;	/* 00H reserved */
2807 	}
2808 
2809 
2810 
2811       /* Byte 29, 349: RIF:reserved:padding type */
2812       if (data->image_composition == LINEART
2813 	  || data->image_composition == HALFTONE)
2814 	{
2815 	  if (s->val[OPT_NEGATIVE].w)
2816 	    data->byte29 |= (1 << 7);	/* set bit 7 */
2817 	  else
2818 	    data->byte29 &= ~(1 << 7);	/* unset bit 7 */
2819 	}
2820       /* Padding Type */
2821       data->byte29 |=
2822 	(paddingtype[get_paddingtype_id (s->val[OPT_PADDING_TYPE].s)].
2823 	 val & 0x07);
2824 
2825       /* Bit Ordering:
2826        *     Manual Says DEFAULT: [1111 1111][1111 1000]
2827        * Bits15-8 reserved;
2828        * Bit7: '0'-Normal '1'-Mirroring
2829        * Bit6-4: Reserved
2830        * Bit3: '0'-arrangement from MSB in grayscale mode
2831        *       '1'-arrangement from LSB in grayscale mode
2832        *    2: '0'-unpacked 4-bits grayscale [DEFAULT]
2833        *       '1'-packed 4-bits grayscale
2834        *    1: '0'-output from LSB of each word [DEFAULT]
2835        *       '1'-output from MSB of each word
2836        *    0: '0'-output from bit 0 of each byte [DEFAULT]
2837        *       '1'-output from bit 7 of each byte
2838        */
2839       _lto2b (0x007, &data->bit_ordering[0]);	/* Set to Packed4bitGray, MSB, MSbit */
2840 
2841       /* Compression Type and Argument NOT SUPPORTED in this scanner */
2842       data->compression_type = 0x00;
2843       data->compression_arg = 0x02;
2844 
2845       /* Byte42:  MRIF:Filtering:GammaID */
2846       if (data->image_composition == GRAYSCALE)
2847 	{
2848 	  if (s->val[OPT_NEGATIVE].w)
2849 	    data->byte42 &= ~(1 << 7);	/* unset bit 7 */
2850 	  else
2851 	    data->byte42 |= (1 << 7);	/* set bit 7 */
2852 	  data->byte42 |= (get_grayfilter_val (s->val[OPT_GRAYFILTER].s) & (7 << 4));	/* set bits 6-4 to GRAYFILTER */
2853 	}
2854       else
2855 	{
2856 	  data->byte42 &= ~(1 << 7);	/* unset bit 7 */
2857 	  data->byte42 &= ~(7 << 4);	/* unset bits 6-4 */
2858 	}
2859       /* Bytes 45, 365 Binary Filtering for lineart and halftone can be set when option IPU is installed */
2860       if ((id = get_noisematrix_id (s->val[OPT_NOISEREMOVAL].s)) != 0)
2861 	{
2862 	  data->binary_filtering |= (1 << 7);	/* set bit 7 */
2863 	  data->binary_filtering |= noisematrix[id].val;	/* 00H, 01H, 02H; 03H:Reserved */
2864 	}
2865       if (s->val[OPT_SMOOTHING].w == SANE_TRUE)
2866 	data->binary_filtering |= (1 << 6);	/* set bit 6 */
2867 
2868       /* Automatic separation, automatic binarization, and SECTION is available if Image Processing Unit is installed */
2869       if (s->hw->info.hasIPU)
2870 	{
2871 	  /* Byte 48: Automatic Separation */
2872 	  data->automatic_separation =
2873 	    get_auto_separation_val (s->val[OPT_AUTOSEP].s);
2874 	  /* Byte 50: Automatic Binarization */
2875 	  data->automatic_binarization =
2876 	    get_auto_binarization_val (s->val[OPT_AUTOBIN].s);
2877 	  /* fill in values for each section
2878 	     for(j=0; j<NumSec; j++){
2879 	     wbuf[i].winsec[j].ulx
2880 	     wbuf[i].winsec[j].uly
2881 	     wbuf[i].winsec[j].width
2882 	     wbuf[i].winsec[j].length
2883 	     wbuf[i].winsec[j].binary_filtering
2884 	     wbuf[i].winsec[j].threshold
2885 	     wbuf[i].winsec[j].image_composition
2886 	     wbuf[i].winsec[j].halftone_id
2887 	     wbuf[i].winsec[j].halftone_arg
2888 	     }
2889 	   */
2890 	}
2891     }
2892   DBG (DBG_proc, "<< set_window_data\n");
2893   return (SANE_STATUS_GOOD);
2894 }
2895 
2896 SANE_Status
sane_start(SANE_Handle handle)2897 sane_start (SANE_Handle handle)	/* begin scanning */
2898 {
2899   HS2P_Scanner *s = handle;
2900   SANE_Status status;
2901   SWD wbuf;			/* Set Window Data: hdr + data */
2902   GWD gbuf;			/* Get Window Data: hdr + data */
2903   SANE_Byte mode, prefeed, mwt = 0;
2904 
2905   DBG (DBG_proc, ">> sane_start\n");
2906   s->cancelled = SANE_FALSE;
2907 
2908   if (s->another_side)
2909     {
2910       /* Number of bytes to read for one side of sheet */
2911       s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
2912       DBG (DBG_info,
2913 	   "SIDE#2 %d pixels per line, %d bytes, %d lines high, dpi=%d\n",
2914 	   s->params.pixels_per_line, s->params.bytes_per_line,
2915 	   s->params.lines, (int) s->val[OPT_Y_RESOLUTION].w);
2916       s->scanning = SANE_TRUE;
2917       s->cancelled = SANE_FALSE;
2918       s->another_side = SANE_FALSE;	/* This is side 2, so no more sides */
2919       DBG (DBG_proc, "<< sane_start\n");
2920       return (SANE_STATUS_GOOD);
2921     }
2922 
2923   if (s->scanning)
2924     {
2925       DBG (DBG_info, "sane_start: device busy\n");
2926       return SANE_STATUS_DEVICE_BUSY;
2927     }
2928 
2929   /* Let's start a new scan */
2930 
2931   if ((status = sane_get_parameters (s, 0)) != SANE_STATUS_GOOD)
2932     {				/* get preliminary parameters */
2933       DBG (DBG_error, "sane_start: sane_get_parameters failed: %s\n",
2934 	   sane_strstatus (status));
2935       return (status);
2936     }
2937 
2938   DBG (DBG_info, ">> sane_start: trying to open: name=\"%s\" fd=%d\n",
2939        s->hw->sane.name, s->fd);
2940   if ((status =
2941        sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler,
2942 			&(s->hw->sense_data))) != SANE_STATUS_GOOD)
2943     {
2944       DBG (DBG_error, "sane_start: open of %s failed: %d %s\n",
2945 	   s->hw->sane.name, status, sane_strstatus (status));
2946       return (status);
2947     }
2948   DBG (DBG_info, ">>sane_start: OPENED \"%s\" fd=%d\n", s->hw->sane.name,
2949        s->fd);
2950 
2951   if ((status = test_unit_ready (s->fd)) != SANE_STATUS_GOOD)
2952     {
2953       DBG (DBG_error, "sane_start: test_unit_ready() failed: %s\n",
2954 	   sane_strstatus (status));
2955       sanei_scsi_close (s->fd);
2956       s->fd = -1;
2957       return status;
2958     }
2959 
2960 
2961   if ((status = reserve_unit (s->fd)) != SANE_STATUS_GOOD)
2962     {
2963       DBG (DBG_error, "sane_start: reserve_unit() failed: %s\n",
2964 	   sane_strstatus (status));
2965       sanei_scsi_close (s->fd);
2966       s->fd = -1;
2967       return (status);
2968     }
2969 
2970   /* NOW SET UP SCANNER ONCE PER BATCH */
2971 
2972   DBG (DBG_info, "sane_start: setting basic measurement unit to mm\n");
2973   if ((status = set_basic_measurement_unit (s->fd, s->hw->info.bmu)))
2974     {
2975       DBG (DBG_error, "set_basic_measurment_unit failed: %s\n",
2976 	   sane_strstatus (status));
2977       release_unit (s->fd);
2978       sanei_scsi_close (s->fd);
2979       s->fd = -1;
2980       return (status);
2981     }
2982 
2983   if (get_scan_source_id (s->val[OPT_SCAN_SOURCE].s) == 0)
2984     {
2985       mode = FLATBED;
2986     }
2987   else
2988     {
2989       mode = (s->val[OPT_DUPLEX].w) ? DUPLEX : SIMPLEX;
2990     }
2991 
2992   prefeed = s->val[OPT_PREFEED].w ? 0x04 : 0x00;
2993   DBG (DBG_info, "sane_start: setting scan source to %d %s\n", mode,
2994        (SANE_String) s->val[OPT_SCAN_SOURCE].s);
2995   DBG (DBG_info, "sane_start: setting prefeed to %d\n", prefeed);
2996   if ((status =
2997        set_adf_control (s->fd, &mode, &prefeed, &mwt)) != SANE_STATUS_GOOD)
2998     {
2999       DBG (DBG_error, "sane_start: error set_adf_control: %s\n",
3000 	   sane_strstatus (status));
3001       release_unit (s->fd);
3002       sanei_scsi_close (s->fd);
3003       s->fd = -1;
3004       return (SANE_STATUS_INVAL);
3005     }
3006 
3007 
3008   DBG (DBG_info, "sane_start: setting endorser control to %d\n",
3009        s->val[OPT_ENDORSER].w);
3010   if ((status =
3011        set_endorser_control (s->fd,
3012 			     &s->val[OPT_ENDORSER].w)) != SANE_STATUS_GOOD)
3013     {
3014       DBG (DBG_error, "set_endorser_control failed: %s\n",
3015 	   sane_strstatus (status));
3016       release_unit (s->fd);
3017       sanei_scsi_close (s->fd);
3018       s->fd = -1;
3019       return (status);
3020     }
3021   if (s->val[OPT_ENDORSER].w)
3022     {
3023       DBG (DBG_info, "sane_start: setting endorser string to %s\n",
3024 	   s->val[OPT_ENDORSER_STRING].s);
3025       if ((status =
3026 	   set_endorser_string (s->fd,
3027 				(SANE_String) s->val[OPT_ENDORSER_STRING].
3028 				s)) != SANE_STATUS_GOOD)
3029 	{
3030 	  DBG (DBG_error, "set_endorser_string failed: %s\n",
3031 	       sane_strstatus (status));
3032 	  release_unit (s->fd);
3033 	  sanei_scsi_close (s->fd);
3034 	  s->fd = -1;
3035 	  return (status);
3036 	}
3037     }
3038 
3039   DBG (DBG_info, "sane_start: setting scan_wait_mode to %d\n",
3040        s->val[OPT_SCAN_WAIT_MODE].w);
3041   if ((status =
3042        set_scan_wait_mode (s->fd,
3043 			   s->val[OPT_SCAN_WAIT_MODE].w)) != SANE_STATUS_GOOD)
3044     {
3045       DBG (DBG_error, "set_scan_wait_mode failed: %s\n",
3046 	   sane_strstatus (status));
3047       release_unit (s->fd);
3048       sanei_scsi_close (s->fd);
3049       s->fd = -1;
3050       return (status);
3051     }
3052   DBG (DBG_info, "sane_start: setting white_balance to %d\n",
3053        s->val[OPT_WHITE_BALANCE].w);
3054   if ((status =
3055        set_white_balance (s->fd,
3056 			  &s->val[OPT_WHITE_BALANCE].w)) != SANE_STATUS_GOOD)
3057     {
3058       DBG (DBG_error, "set_white_balance failed: %s\n",
3059 	   sane_strstatus (status));
3060       release_unit (s->fd);
3061       sanei_scsi_close (s->fd);
3062       s->fd = -1;
3063       return (status);
3064     }
3065 
3066   if (s->val[OPT_CUSTOM_GAMMA].b)
3067     {				/* Custom Gamma needs to be sent to scanner */
3068       DBG (DBG_info, "sane_start: setting custom gamma\n");
3069       if ((status = hs2p_send_gamma (s)))
3070 	{
3071 	  DBG (DBG_error, "hs2p_send_gamma failed: %s\n",
3072 	       sane_strstatus (status));
3073 	  release_unit (s->fd);
3074 	  sanei_scsi_close (s->fd);
3075 	  s->fd = -1;
3076 	  return (status);
3077 	}
3078       /* We succeeded, so we don't need to upload this vector again (unless user modifies gamma table) */
3079       s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE;
3080     }
3081 
3082 
3083   DBG (DBG_info, "sane_start: filling in window data buffer \n");
3084   if ((status = set_window_data (s, &wbuf)) != SANE_STATUS_GOOD)
3085     {
3086       DBG (DBG_error, "set_window_data failed: %s\n",
3087 	   sane_strstatus (status));
3088       release_unit (s->fd);
3089       sanei_scsi_close (s->fd);
3090       s->fd = -1;
3091       return (status);
3092     }
3093   DBG (DBG_info, "sane_start: sending SET WINDOW DATA\n");
3094   if ((status = set_window (s->fd, &wbuf)) != SANE_STATUS_GOOD)
3095     {
3096       DBG (DBG_error, "SET WINDOW DATA failed: %s\n",
3097 	   sane_strstatus (status));
3098       print_window_data (&wbuf);
3099       release_unit (s->fd);
3100       sanei_scsi_close (s->fd);
3101       s->fd = -1;
3102       return (status);
3103     }
3104   DBG (DBG_info, "sane_start: sending GET WINDOW\n");
3105   memset (&gbuf, 0, sizeof (gbuf));	/* CLEAR wbuf */
3106   if ((status = get_window (s->fd, &gbuf)) != SANE_STATUS_GOOD)
3107     {
3108       DBG (DBG_error, "GET WINDOW failed: %s\n", sane_strstatus (status));
3109       release_unit (s->fd);
3110       sanei_scsi_close (s->fd);
3111       s->fd = -1;
3112       return (status);
3113     }
3114 
3115   /* DONE WITH SETTING UP SCANNER ONCE PER BATCH */
3116 
3117   s->EOM = SANE_FALSE;
3118   if (mode != FLATBED)
3119     {
3120       if ((status =
3121 	   get_hs2p_data (s, DATA_TYPE_ADF_STATUS,
3122 			  DATA_TYPE_EOL)) != SANE_STATUS_GOOD)
3123 	{
3124 	  DBG (DBG_error, "sane_start: error reading adf_status:  %s\n",
3125 	       sane_strstatus (status));
3126 	  return (status);
3127 	}
3128       if ((s->data.adf_status & 0x00) == 0x01)
3129 	{
3130 	  DBG (DBG_warning, "sane_start: No document on ADF\n");
3131 	  return (SANE_STATUS_NO_DOCS);
3132 	}
3133       else if ((s->data.adf_status & 0x02) == 0x02)
3134 	{
3135 	  DBG (DBG_warning, "sane_start: ADF cover open!\n");
3136 	  return (SANE_STATUS_COVER_OPEN);
3137 	}
3138     }
3139 
3140 
3141   status = trigger_scan (s);
3142   if (status != SANE_STATUS_GOOD)
3143     {
3144       DBG (DBG_error, "start of scan failed: %s\n", sane_strstatus (status));
3145       print_window_data (&wbuf);
3146       /* this line introduced not to freeze xscanimage */
3147       /*do_cancel (s); */
3148       return status;
3149     }
3150   /* Wait for scanner to become ready to transmit data */
3151   status = hs2p_wait_ready (s);
3152   if (status != SANE_STATUS_GOOD)
3153     {
3154       DBG (DBG_error, "GET DATA STATUS failed: %s\n",
3155 	   sane_strstatus (status));
3156       return (status);
3157     }
3158 
3159   s->another_side = (mode == DUPLEX) ? SANE_TRUE : SANE_FALSE;
3160   /* Number of bytes to read for one side of sheet */
3161   DBG (DBG_info, "ANOTHER SIDE = %s\n", (s->another_side) ? "TRUE" : "FALSE");
3162   s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
3163   DBG (DBG_info, "%d pixels per line, %d bytes, %d lines high, dpi=%d\n",
3164        s->params.pixels_per_line, s->params.bytes_per_line,
3165        s->params.lines, (int) s->val[OPT_Y_RESOLUTION].w);
3166   s->scanning = SANE_TRUE;
3167   s->cancelled = SANE_FALSE;
3168 
3169   DBG (DBG_proc, "<< sane_start\n");
3170   return (SANE_STATUS_GOOD);
3171 }
3172 
3173 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)3174 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
3175 	   SANE_Int * len)
3176 {
3177   HS2P_Scanner *s = handle;
3178   SANE_Status status;
3179   size_t nread, bytes_requested, i, start;
3180   SANE_Byte color;
3181   DBG (DBG_proc, ">> sane_read\n");
3182 
3183   *len = 0;
3184 
3185   DBG (DBG_info, "sane_read: bytes left to read: %ld\n",
3186        (u_long) s->bytes_to_read);
3187 
3188   if (s->bytes_to_read == 0)
3189     {				/* We've reached the end of one side of sheet */
3190       if (!s->another_side)
3191 	{
3192 	  do_cancel (s);
3193 	  return (SANE_STATUS_EOF);
3194 	}
3195       else
3196 	{
3197 	  /* let frontend call sane_start again to reset bytes_to_read */
3198 	  DBG (DBG_proc, "<< sane_read: getting another side\n");
3199 	  return (SANE_STATUS_EOF);
3200 	}
3201     }
3202 
3203   if (s->cancelled)
3204     {
3205       DBG (DBG_info, "sane_read: cancelled!\n");
3206       return SANE_STATUS_CANCELLED;
3207     }
3208   if (!s->scanning)
3209     {
3210       DBG (DBG_info, "sane_read: scanning is false!\n");
3211       return (do_cancel (s));
3212     }
3213 
3214   nread = max_len;
3215   if (nread > s->bytes_to_read)
3216     nread = s->bytes_to_read;
3217   bytes_requested = nread;
3218   start = 0;
3219 
3220 pad:
3221   if (s->EOM)
3222     {
3223       if (s->val[OPT_PADDING].w)
3224 	{
3225 	  DBG (DBG_info, "sane_read s->EOM padding from %ld to %ld\n",
3226 	       (u_long) start, (u_long) bytes_requested);
3227 	  color = (s->val[OPT_NEGATIVE].w) ? 0 : 255;
3228 	  /* pad to requested length */
3229 	  for (i = start; i < bytes_requested; i++)
3230 	    buf[i] = color;
3231 	  nread = bytes_requested;	/* we've padded to bytes_requested */
3232 	  *len = nread;
3233 	  s->bytes_to_read -= nread;
3234 	}
3235       else			/* TRUNCATE: should never reach here */
3236 	{
3237 	  *len = nread;
3238 	  s->bytes_to_read = 0;	/* EOM */
3239 	}
3240     }
3241   else
3242     {
3243       DBG (DBG_info, "sane_read: trying to read %ld bytes\n", (u_long) nread);
3244       status = read_data (s->fd, buf, &nread, DATA_TYPE_IMAGE, DTQ);
3245       switch (status)
3246 	{
3247 	case SANE_STATUS_NO_DOCS:
3248 	  DBG (DBG_error, "sane_read: End-Of-Medium detected\n");
3249 	  s->EOM = SANE_TRUE;
3250 	  /*
3251 	   * If status != SANE_STATUS_GOOD, then sense_handler() has already
3252 	   * been called and the sanei_* functions have already gotten the
3253 	   * sense data buffer (which apparently clears the error condition)
3254 	   * so the following doesn't work:
3255 	   get_sense_data (s->fd, &(s->hw->sense_data));
3256 	   print_sense_data (&(s->hw->sense_data));
3257 	   */
3258 	  start = (isset_ILI (s->hw->sense_data)) ?	/* Invalid Length Indicator */
3259 	    bytes_requested - _4btol (s->hw->sense_data.information) : nread;
3260 	  goto pad;
3261 	  break;
3262 	case SANE_STATUS_GOOD:
3263 	  *len = nread;
3264 	  s->bytes_to_read -= nread;
3265 	  break;
3266 	default:
3267 	  DBG (DBG_error, "sane_read: read error\n");
3268 	  do_cancel (s);
3269 	  return (SANE_STATUS_IO_ERROR);
3270 	}
3271     }
3272   DBG (DBG_proc, "<< sane_read\n");
3273   return (SANE_STATUS_GOOD);
3274 }
3275 
3276 
3277 void
sane_cancel(SANE_Handle handle)3278 sane_cancel (SANE_Handle handle)
3279 {
3280   HS2P_Scanner *s = handle;
3281   DBG (DBG_proc, ">> sane_cancel\n");
3282 
3283   if (s->scanning)
3284     {				/* if batchmode is enabled, then call set_window to abort the batch
3285 				   if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) {
3286 				   DBG(5, "sane_cancel: calling set_window to abort batch\n");
3287 				   set_window(s, BH_BATCH_ABORT);
3288 				   }   */
3289       do_cancel (s);
3290     }
3291 
3292 
3293 
3294   DBG (DBG_proc, "<< sane_cancel\n");
3295 }
3296 
3297 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)3298 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
3299 {
3300   DBG (DBG_proc, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n",
3301        handle, non_blocking);
3302   DBG (DBG_proc, "<< sane_set_io_mode\n");
3303 
3304   return SANE_STATUS_UNSUPPORTED;
3305 }
3306 
3307 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)3308 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
3309 {
3310 #ifdef NONBLOCKSUPPORTED
3311   HS2P_Scanner *s = handle;
3312 #endif
3313   DBG (DBG_proc, ">> sane_get_select_fd (handle = %p, fd = %p)\n", handle,
3314        (void *) fd);
3315 
3316 #ifdef NONBLOCKSUPPORTED
3317   if (s->fd < 0)
3318     {
3319       DBG (DBG_proc, "<< sane_get_select_fd\n");
3320       return SANE_STATUS_INVAL;
3321     }
3322   *fd = s->fd;
3323   return SANE_STATUS_GOOD;
3324 #else
3325   handle = handle;
3326   fd = fd;			/* get rid of compiler warning */
3327   DBG (DBG_proc, "<< sane_get_select_fd\n");
3328   return SANE_STATUS_UNSUPPORTED;
3329 #endif
3330 }
3331