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