1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
4 Copyright (C) 2002 - 2007 Henning Geinitz <sane@geinitz.org>
5 Copyright (C) 2009 Stéphane Voltz <stef.dev@free.fr> for sheetfed
6 calibration code.
7
8 This file is part of the SANE package.
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <https://www.gnu.org/licenses/>.
22
23 As a special exception, the authors of SANE give permission for
24 additional uses of the libraries contained in this release of SANE.
25
26 The exception is that, if you link a SANE library with other files
27 to produce an executable, this does not by itself cause the
28 resulting executable to be covered by the GNU General Public
29 License. Your use of that executable is in no way restricted on
30 account of linking the SANE library code into it.
31
32 This exception does not, however, invalidate any other reasons why
33 the executable file might be covered by the GNU General Public
34 License.
35
36 If you submit changes to SANE to the maintainers to be included in
37 a subsequent release, you agree by submitting the changes that
38 those changes may be distributed with this exception intact.
39
40 If you write modifications of your own for SANE, it is your choice
41 whether to permit this exception to apply to your modifications.
42 If you do not wish that, delete this exception notice.
43 */
44
45 /*
46 * SANE backend for Grandtech GT-6801 and GT-6816 based scanners
47 */
48
49 #include "../include/sane/config.h"
50
51 #define BUILD 84
52 #define MAX_DEBUG
53 #define WARMUP_TIME 60
54 #define CALIBRATION_HEIGHT 2.5
55 #define SHORT_TIMEOUT (1 * 1000)
56 #define LONG_TIMEOUT (30 * 1000)
57
58 /* Use a reader process if possible (usually faster) */
59 #if defined (HAVE_SYS_SHM_H) && (!defined (USE_PTHREAD)) && (!defined (HAVE_OS2_H))
60 #define USE_FORK
61 #define SHM_BUFFERS 10
62 #endif
63
64 #define TUNE_CALIBRATOR
65
66 /* Send coarse white or black calibration to stdout */
67 #if 0
68 #define SAVE_WHITE_CALIBRATION
69 #endif
70 #if 0
71 #define SAVE_BLACK_CALIBRATION
72 #endif
73
74 /* Debug calibration, print total brightness of the scanned image */
75 #if 0
76 #define DEBUG_BRIGHTNESS
77 #endif
78
79 /* Debug calibration, print black mark values */
80 #if 0
81 #define DEBUG_BLACK
82 #endif
83
84 #include <ctype.h>
85 #include <errno.h>
86 #include <fcntl.h>
87 #include <limits.h>
88 #include <signal.h>
89 #include <stdio.h>
90 #include <stdlib.h>
91 #include <string.h>
92 #include <unistd.h>
93 #include <sys/time.h>
94 #include <time.h>
95 #include <math.h>
96 #include <dirent.h>
97
98 #include "../include/_stdint.h"
99
100 #include "../include/sane/sane.h"
101 #include "../include/sane/sanei.h"
102 #include "../include/sane/saneopts.h"
103
104 #define BACKEND_NAME gt68xx
105
106 #include "../include/sane/sanei_backend.h"
107 #include "../include/sane/sanei_config.h"
108
109 #ifndef SANE_I18N
110 #define SANE_I18N(text) text
111 #endif
112
113 #include "gt68xx.h"
114 #include "gt68xx_high.c"
115 #include "gt68xx_devices.c"
116
117 static SANE_Int num_devices = 0;
118 static GT68xx_Device *first_dev = 0;
119 static GT68xx_Scanner *first_handle = 0;
120 static const SANE_Device **devlist = 0;
121 /* Array of newly attached devices */
122 static GT68xx_Device **new_dev = 0;
123 /* Length of new_dev array */
124 static SANE_Int new_dev_len = 0;
125 /* Number of entries allocated for new_dev */
126 static SANE_Int new_dev_alloced = 0;
127 /* Is this computer little-endian ?*/
128 SANE_Bool little_endian;
129 SANE_Bool debug_options = SANE_FALSE;
130
131 static SANE_String_Const mode_list[] = {
132 SANE_VALUE_SCAN_MODE_COLOR,
133 SANE_VALUE_SCAN_MODE_GRAY,
134 SANE_VALUE_SCAN_MODE_LINEART,
135 0
136 };
137
138 static SANE_String_Const gray_mode_list[] = {
139 GT68XX_COLOR_RED,
140 GT68XX_COLOR_GREEN,
141 GT68XX_COLOR_BLUE,
142 0
143 };
144
145 static SANE_String_Const source_list[] = {
146 SANE_I18N ("Flatbed"),
147 SANE_I18N ("Transparency Adapter"),
148 0
149 };
150
151 static SANE_Range x_range = {
152 SANE_FIX (0.0), /* minimum */
153 SANE_FIX (216.0), /* maximum */
154 SANE_FIX (0.0) /* quantization */
155 };
156
157 static SANE_Range y_range = {
158 SANE_FIX (0.0), /* minimum */
159 SANE_FIX (299.0), /* maximum */
160 SANE_FIX (0.0) /* quantization */
161 };
162
163 static SANE_Range gamma_range = {
164 SANE_FIX (0.01), /* minimum */
165 SANE_FIX (5.0), /* maximum */
166 SANE_FIX (0.01) /* quantization */
167 };
168
169 static const SANE_Range u8_range = {
170 0, /* minimum */
171 255, /* maximum */
172 0 /* quantization */
173 };
174
175 /* Test if this machine is little endian (from coolscan.c) */
176 static SANE_Bool
calc_little_endian(void)177 calc_little_endian (void)
178 {
179 SANE_Int testvalue = 255;
180 uint8_t *firstbyte = (uint8_t *) & testvalue;
181
182 if (*firstbyte == 255)
183 return SANE_TRUE;
184 return SANE_FALSE;
185 }
186
187 static size_t
max_string_size(const SANE_String_Const strings[])188 max_string_size (const SANE_String_Const strings[])
189 {
190 size_t size, max_size = 0;
191 SANE_Int i;
192
193 for (i = 0; strings[i]; ++i)
194 {
195 size = strlen (strings[i]) + 1;
196 if (size > max_size)
197 max_size = size;
198 }
199 return max_size;
200 }
201
202 static SANE_Status
get_afe_values(SANE_String_Const cp,GT68xx_AFE_Parameters * afe)203 get_afe_values (SANE_String_Const cp, GT68xx_AFE_Parameters * afe)
204 {
205 SANE_Char *word, *end;
206 int i;
207
208 for (i = 0; i < 6; i++)
209 {
210 cp = sanei_config_get_string (cp, &word);
211 if (word && *word)
212 {
213 long int long_value;
214 errno = 0;
215 long_value = strtol (word, &end, 0);
216
217 if (end == word)
218 {
219 DBG (5, "get_afe_values: can't parse %d. parameter `%s'\n",
220 i + 1, word);
221 free (word);
222 word = 0;
223 return SANE_STATUS_INVAL;
224 }
225 else if (errno)
226 {
227 DBG (5, "get_afe_values: can't parse %d. parameter `%s' "
228 "(%s)\n", i + 1, word, strerror (errno));
229 free (word);
230 word = 0;
231 return SANE_STATUS_INVAL;
232 }
233 else if (long_value < 0)
234 {
235 DBG (5, "get_afe_values: %d. parameter < 0 (%d)\n", i + 1,
236 (int) long_value);
237 free (word);
238 word = 0;
239 return SANE_STATUS_INVAL;
240 }
241 else if (long_value > 0x3f)
242 {
243 DBG (5, "get_afe_values: %d. parameter > 0x3f (%d)\n", i + 1,
244 (int) long_value);
245 free (word);
246 word = 0;
247 return SANE_STATUS_INVAL;
248 }
249 else
250 {
251 DBG (5, "get_afe_values: %d. parameter set to 0x%02x\n", i + 1,
252 (int) long_value);
253 switch (i)
254 {
255 case 0:
256 afe->r_offset = (SANE_Byte) long_value;
257 break;
258 case 1:
259 afe->r_pga = (SANE_Byte) long_value;
260 break;
261 case 2:
262 afe->g_offset = (SANE_Byte) long_value;
263 break;
264 case 3:
265 afe->g_pga = (SANE_Byte) long_value;
266 break;
267 case 4:
268 afe->b_offset = (SANE_Byte) long_value;
269 break;
270 case 5:
271 afe->b_pga = (SANE_Byte) long_value;
272 break;
273 }
274 free (word);
275 word = 0;
276 }
277 }
278 else
279 {
280 DBG (5, "get_afe_values: option `afe' needs 6 parameters\n");
281 return SANE_STATUS_INVAL;
282 }
283 }
284 return SANE_STATUS_GOOD;
285 }
286
287 static SANE_Status
setup_scan_request(GT68xx_Scanner * s,GT68xx_Scan_Request * scan_request)288 setup_scan_request (GT68xx_Scanner * s, GT68xx_Scan_Request * scan_request)
289 {
290
291 if (s->dev->model->flags & GT68XX_FLAG_MIRROR_X)
292 scan_request->x0 =
293 s->opt[OPT_TL_X].constraint.range->max - s->val[OPT_BR_X].w;
294 else
295 scan_request->x0 = s->val[OPT_TL_X].w;
296 scan_request->y0 = s->val[OPT_TL_Y].w;
297 scan_request->xs = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w;
298 scan_request->ys = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w;
299
300 if (s->val[OPT_FULL_SCAN].w == SANE_TRUE)
301 {
302 scan_request->x0 -= s->dev->model->x_offset;
303 scan_request->y0 -= (s->dev->model->y_offset);
304 scan_request->xs += s->dev->model->x_offset;
305 scan_request->ys += s->dev->model->y_offset;
306 }
307
308 scan_request->xdpi = s->val[OPT_RESOLUTION].w;
309 if (scan_request->xdpi > s->dev->model->optical_xdpi)
310 scan_request->xdpi = s->dev->model->optical_xdpi;
311 scan_request->ydpi = s->val[OPT_RESOLUTION].w;
312
313 if (IS_ACTIVE (OPT_BIT_DEPTH) && !s->val[OPT_PREVIEW].w)
314 scan_request->depth = s->val[OPT_BIT_DEPTH].w;
315 else
316 scan_request->depth = 8;
317
318 if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)
319 scan_request->color = SANE_TRUE;
320 else
321 scan_request->color = SANE_FALSE;
322
323 if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
324 {
325 SANE_Int xs =
326 SANE_UNFIX (scan_request->xs) * scan_request->xdpi / MM_PER_INCH +
327 0.5;
328
329 if (xs % 8)
330 {
331 scan_request->xs =
332 SANE_FIX ((xs - (xs % 8)) * MM_PER_INCH / scan_request->xdpi);
333 DBG (5, "setup_scan_request: lineart mode, %d pixels %% 8 = %d\n",
334 xs, xs % 8);
335 }
336 }
337
338 scan_request->calculate = SANE_FALSE;
339 scan_request->lamp = SANE_TRUE;
340 scan_request->mbs = SANE_FALSE;
341
342 if (strcmp (s->val[OPT_SOURCE].s, "Transparency Adapter") == 0)
343 scan_request->use_ta = SANE_TRUE;
344 else
345 scan_request->use_ta = SANE_FALSE;
346
347 return SANE_STATUS_GOOD;
348 }
349
350 static SANE_Status
calc_parameters(GT68xx_Scanner * s)351 calc_parameters (GT68xx_Scanner * s)
352 {
353 SANE_String val;
354 SANE_Status status = SANE_STATUS_GOOD;
355 GT68xx_Scan_Request scan_request;
356 GT68xx_Scan_Parameters scan_params;
357
358 DBG (5, "calc_parameters: start\n");
359 val = s->val[OPT_MODE].s;
360
361 s->params.last_frame = SANE_TRUE;
362 if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0
363 || strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)
364 s->params.format = SANE_FRAME_GRAY;
365 else /* Color */
366 s->params.format = SANE_FRAME_RGB;
367
368 setup_scan_request (s, &scan_request);
369 scan_request.calculate = SANE_TRUE;
370
371 status = gt68xx_device_setup_scan (s->dev, &scan_request, SA_SCAN,
372 &scan_params);
373 if (status != SANE_STATUS_GOOD)
374 {
375 DBG (1, "calc_parameters: gt68xx_device_setup_scan returned: %s\n",
376 sane_strstatus (status));
377 return status;
378 }
379
380 if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)
381 s->params.depth = 1;
382 else
383 s->params.depth = scan_params.depth;
384
385 s->params.lines = scan_params.pixel_ys;
386 s->params.pixels_per_line = scan_params.pixel_xs;
387 /* Inflate X if necessary */
388 if (s->val[OPT_RESOLUTION].w > s->dev->model->optical_xdpi)
389 s->params.pixels_per_line *=
390 (s->val[OPT_RESOLUTION].w / s->dev->model->optical_xdpi);
391 s->params.bytes_per_line = s->params.pixels_per_line;
392 if (s->params.depth > 8)
393 {
394 s->params.depth = 16;
395 s->params.bytes_per_line *= 2;
396 }
397 else if (s->params.depth == 1)
398 s->params.bytes_per_line /= 8;
399
400 if (s->params.format == SANE_FRAME_RGB)
401 s->params.bytes_per_line *= 3;
402
403 DBG (5, "calc_parameters: exit\n");
404 return status;
405 }
406
407 static SANE_Status
create_bpp_list(GT68xx_Scanner * s,SANE_Int * bpp)408 create_bpp_list (GT68xx_Scanner * s, SANE_Int * bpp)
409 {
410 int count;
411
412 for (count = 0; bpp[count] != 0; count++)
413 ;
414 s->bpp_list[0] = count;
415 for (count = 0; bpp[count] != 0; count++)
416 {
417 s->bpp_list[s->bpp_list[0] - count] = bpp[count];
418 }
419 return SANE_STATUS_GOOD;
420 }
421
422 static SANE_Status
init_options(GT68xx_Scanner * s)423 init_options (GT68xx_Scanner * s)
424 {
425 SANE_Int option, count;
426 SANE_Status status;
427 SANE_Word *dpi_list;
428 GT68xx_Model *model = s->dev->model;
429 SANE_Bool has_ta = SANE_FALSE;
430
431 DBG (5, "init_options: start\n");
432
433 memset (s->opt, 0, sizeof (s->opt));
434 memset (s->val, 0, sizeof (s->val));
435
436 for (option = 0; option < NUM_OPTIONS; ++option)
437 {
438 s->opt[option].size = sizeof (SANE_Word);
439 s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
440 }
441 s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
442 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
443 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
444 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
445 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
446 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
447
448 /* "Mode" group: */
449 s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode");
450 s->opt[OPT_MODE_GROUP].desc = "";
451 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
452 s->opt[OPT_MODE_GROUP].size = 0;
453 s->opt[OPT_MODE_GROUP].cap = 0;
454 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
455
456 /* scan mode */
457 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
458 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
459 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
460 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
461 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
462 s->opt[OPT_MODE].size = max_string_size (mode_list);
463 s->opt[OPT_MODE].constraint.string_list = mode_list;
464 s->val[OPT_MODE].s = strdup (SANE_VALUE_SCAN_MODE_GRAY);
465
466 /* scan mode */
467 s->opt[OPT_GRAY_MODE_COLOR].name = "gray-mode-color";
468 s->opt[OPT_GRAY_MODE_COLOR].title = SANE_I18N ("Gray mode color");
469 s->opt[OPT_GRAY_MODE_COLOR].desc =
470 SANE_I18N ("Selects which scan color is used "
471 "gray mode (default: green).");
472 s->opt[OPT_GRAY_MODE_COLOR].type = SANE_TYPE_STRING;
473 s->opt[OPT_GRAY_MODE_COLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST;
474 s->opt[OPT_GRAY_MODE_COLOR].size = max_string_size (gray_mode_list);
475 s->opt[OPT_GRAY_MODE_COLOR].constraint.string_list = gray_mode_list;
476 s->val[OPT_GRAY_MODE_COLOR].s = strdup (GT68XX_COLOR_GREEN);
477
478 /* scan source */
479 s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
480 s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
481 s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
482 s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
483 s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
484 s->opt[OPT_SOURCE].size = max_string_size (source_list);
485 s->opt[OPT_SOURCE].constraint.string_list = source_list;
486 s->val[OPT_SOURCE].s = strdup ("Flatbed");
487 status = gt68xx_device_get_ta_status (s->dev, &has_ta);
488 if (status != SANE_STATUS_GOOD || !has_ta)
489 DISABLE (OPT_SOURCE);
490
491 /* preview */
492 s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
493 s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
494 s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
495 s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
496 s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE;
497 s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
498 s->val[OPT_PREVIEW].w = SANE_FALSE;
499
500 /* lamp on */
501 s->opt[OPT_LAMP_OFF_AT_EXIT].name = SANE_NAME_LAMP_OFF_AT_EXIT;
502 s->opt[OPT_LAMP_OFF_AT_EXIT].title = SANE_TITLE_LAMP_OFF_AT_EXIT;
503 s->opt[OPT_LAMP_OFF_AT_EXIT].desc = SANE_DESC_LAMP_OFF_AT_EXIT;
504 s->opt[OPT_LAMP_OFF_AT_EXIT].type = SANE_TYPE_BOOL;
505 s->opt[OPT_LAMP_OFF_AT_EXIT].unit = SANE_UNIT_NONE;
506 s->opt[OPT_LAMP_OFF_AT_EXIT].constraint_type = SANE_CONSTRAINT_NONE;
507 s->val[OPT_LAMP_OFF_AT_EXIT].w = SANE_TRUE;
508 if (s->dev->model->is_cis && !(s->dev->model->flags & GT68XX_FLAG_CIS_LAMP))
509 DISABLE (OPT_LAMP_OFF_AT_EXIT);
510
511 /* bit depth */
512 s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
513 s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
514 s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
515 s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
516 s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
517 s->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word);
518 s->opt[OPT_BIT_DEPTH].constraint.word_list = 0;
519 s->opt[OPT_BIT_DEPTH].constraint.word_list = s->bpp_list;
520 RIE (create_bpp_list (s, s->dev->model->bpp_gray_values));
521 s->val[OPT_BIT_DEPTH].w = 8;
522 if (s->opt[OPT_BIT_DEPTH].constraint.word_list[0] < 2)
523 DISABLE (OPT_BIT_DEPTH);
524
525 /* resolution */
526 for (count = 0; model->ydpi_values[count] != 0; count++)
527 ;
528 dpi_list = malloc ((count + 1) * sizeof (SANE_Word));
529 if (!dpi_list)
530 return SANE_STATUS_NO_MEM;
531 dpi_list[0] = count;
532 for (count = 0; model->ydpi_values[count] != 0; count++)
533 dpi_list[dpi_list[0] - count] = model->ydpi_values[count];
534 s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
535 s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
536 s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
537 s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
538 s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
539 s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
540 s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
541 s->val[OPT_RESOLUTION].w = 300;
542
543 /* backtrack */
544 s->opt[OPT_BACKTRACK].name = SANE_NAME_BACKTRACK;
545 s->opt[OPT_BACKTRACK].title = SANE_TITLE_BACKTRACK;
546 s->opt[OPT_BACKTRACK].desc = SANE_DESC_BACKTRACK;
547 s->opt[OPT_BACKTRACK].type = SANE_TYPE_BOOL;
548 s->val[OPT_BACKTRACK].w = SANE_FALSE;
549
550 /* "Debug" group: */
551 s->opt[OPT_DEBUG_GROUP].title = SANE_I18N ("Debugging Options");
552 s->opt[OPT_DEBUG_GROUP].desc = "";
553 s->opt[OPT_DEBUG_GROUP].type = SANE_TYPE_GROUP;
554 s->opt[OPT_DEBUG_GROUP].size = 0;
555 s->opt[OPT_DEBUG_GROUP].cap = 0;
556 s->opt[OPT_DEBUG_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
557 if (!debug_options)
558 DISABLE (OPT_DEBUG_GROUP);
559
560 /* auto warmup */
561 s->opt[OPT_AUTO_WARMUP].name = "auto-warmup";
562 s->opt[OPT_AUTO_WARMUP].title = SANE_I18N ("Automatic warmup");
563 s->opt[OPT_AUTO_WARMUP].desc =
564 SANE_I18N ("Warm-up until the lamp's brightness is constant "
565 "instead of insisting on 60 seconds warm-up time.");
566 s->opt[OPT_AUTO_WARMUP].type = SANE_TYPE_BOOL;
567 s->opt[OPT_AUTO_WARMUP].unit = SANE_UNIT_NONE;
568 s->opt[OPT_AUTO_WARMUP].constraint_type = SANE_CONSTRAINT_NONE;
569 s->val[OPT_AUTO_WARMUP].w = SANE_TRUE;
570 if ((s->dev->model->is_cis
571 && !(s->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) || !debug_options)
572 DISABLE (OPT_AUTO_WARMUP);
573
574 /* full scan */
575 s->opt[OPT_FULL_SCAN].name = "full-scan";
576 s->opt[OPT_FULL_SCAN].title = SANE_I18N ("Full scan");
577 s->opt[OPT_FULL_SCAN].desc =
578 SANE_I18N ("Scan the complete scanning area including calibration strip. "
579 "Be careful. Don't select the full height. For testing only.");
580 s->opt[OPT_FULL_SCAN].type = SANE_TYPE_BOOL;
581 s->opt[OPT_FULL_SCAN].unit = SANE_UNIT_NONE;
582 s->opt[OPT_FULL_SCAN].constraint_type = SANE_CONSTRAINT_NONE;
583 s->val[OPT_FULL_SCAN].w = SANE_FALSE;
584 if (!debug_options)
585 DISABLE (OPT_FULL_SCAN);
586
587 /* coarse calibration */
588 s->opt[OPT_COARSE_CAL].name = "coarse-calibration";
589 s->opt[OPT_COARSE_CAL].title = SANE_I18N ("Coarse calibration");
590 s->opt[OPT_COARSE_CAL].desc =
591 SANE_I18N ("Setup gain and offset for scanning automatically. If this "
592 "option is disabled, options for setting the analog frontend "
593 "parameters manually are provided. This option is enabled "
594 "by default. For testing only.");
595 s->opt[OPT_COARSE_CAL].type = SANE_TYPE_BOOL;
596 s->opt[OPT_COARSE_CAL].unit = SANE_UNIT_NONE;
597 s->opt[OPT_COARSE_CAL].constraint_type = SANE_CONSTRAINT_NONE;
598 s->val[OPT_COARSE_CAL].w = SANE_TRUE;
599 if (!debug_options)
600 DISABLE (OPT_COARSE_CAL);
601 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
602 {
603 s->val[OPT_COARSE_CAL].w = SANE_FALSE;
604 DISABLE (OPT_COARSE_CAL);
605 }
606
607 /* coarse calibration only once */
608 s->opt[OPT_COARSE_CAL_ONCE].name = "coarse-calibration-once";
609 s->opt[OPT_COARSE_CAL_ONCE].title =
610 SANE_I18N ("Coarse calibration for first scan only");
611 s->opt[OPT_COARSE_CAL_ONCE].desc =
612 SANE_I18N ("Coarse calibration is only done for the first scan. Works "
613 "with most scanners and can save scanning time. If the image "
614 "brightness is different with each scan, disable this option. "
615 "For testing only.");
616 s->opt[OPT_COARSE_CAL_ONCE].type = SANE_TYPE_BOOL;
617 s->opt[OPT_COARSE_CAL_ONCE].unit = SANE_UNIT_NONE;
618 s->opt[OPT_COARSE_CAL_ONCE].constraint_type = SANE_CONSTRAINT_NONE;
619 s->val[OPT_COARSE_CAL_ONCE].w = SANE_FALSE;
620 if (!debug_options)
621 DISABLE (OPT_COARSE_CAL_ONCE);
622 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
623 DISABLE (OPT_COARSE_CAL_ONCE);
624
625 /* calibration */
626 s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL;
627 s->opt[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL;
628 s->opt[OPT_QUALITY_CAL].desc = SANE_TITLE_QUALITY_CAL;
629 s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL;
630 s->opt[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE;
631 s->opt[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE;
632 s->val[OPT_QUALITY_CAL].w = SANE_TRUE;
633 if (!debug_options)
634 DISABLE (OPT_QUALITY_CAL);
635 /* we disable image correction for scanners that can't calibrate */
636 if ((s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
637 &&(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)))
638 {
639 s->val[OPT_QUALITY_CAL].w = SANE_FALSE;
640 DISABLE (OPT_QUALITY_CAL);
641 }
642
643 /* backtrack lines */
644 s->opt[OPT_BACKTRACK_LINES].name = "backtrack-lines";
645 s->opt[OPT_BACKTRACK_LINES].title = SANE_I18N ("Backtrack lines");
646 s->opt[OPT_BACKTRACK_LINES].desc =
647 SANE_I18N ("Number of lines the scan slider moves back when backtracking "
648 "occurs. That happens when the scanner scans faster than the "
649 "computer can receive the data. Low values cause faster scans "
650 "but increase the risk of omitting lines.");
651 s->opt[OPT_BACKTRACK_LINES].type = SANE_TYPE_INT;
652 s->opt[OPT_BACKTRACK_LINES].unit = SANE_UNIT_NONE;
653 s->opt[OPT_BACKTRACK_LINES].constraint_type = SANE_CONSTRAINT_RANGE;
654 s->opt[OPT_BACKTRACK_LINES].constraint.range = &u8_range;
655 if (s->dev->model->is_cis && !(s->dev->model->flags & GT68XX_FLAG_SHEET_FED))
656 s->val[OPT_BACKTRACK_LINES].w = 0x10;
657 else
658 s->val[OPT_BACKTRACK_LINES].w = 0x3f;
659 if (!debug_options)
660 DISABLE (OPT_BACKTRACK_LINES);
661
662 /* "Enhancement" group: */
663 s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement");
664 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
665 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
666 s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
667 s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
668 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
669
670 /* internal gamma value */
671 s->opt[OPT_GAMMA_VALUE].name = "gamma-value";
672 s->opt[OPT_GAMMA_VALUE].title = SANE_I18N ("Gamma value");
673 s->opt[OPT_GAMMA_VALUE].desc =
674 SANE_I18N ("Sets the gamma value of all channels.");
675 s->opt[OPT_GAMMA_VALUE].type = SANE_TYPE_FIXED;
676 s->opt[OPT_GAMMA_VALUE].unit = SANE_UNIT_NONE;
677 s->opt[OPT_GAMMA_VALUE].constraint_type = SANE_CONSTRAINT_RANGE;
678 s->opt[OPT_GAMMA_VALUE].constraint.range = &gamma_range;
679 s->opt[OPT_GAMMA_VALUE].cap |= SANE_CAP_EMULATED;
680 s->val[OPT_GAMMA_VALUE].w = s->dev->gamma_value;
681
682 /* threshold */
683 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
684 s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
685 s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
686 s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
687 s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
688 s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
689 s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
690 s->val[OPT_THRESHOLD].w = 128;
691 DISABLE (OPT_THRESHOLD);
692
693 /* "Geometry" group: */
694 s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry");
695 s->opt[OPT_GEOMETRY_GROUP].desc = "";
696 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
697 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
698 s->opt[OPT_GEOMETRY_GROUP].size = 0;
699 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
700
701 x_range.max = model->x_size;
702 y_range.max = model->y_size;
703
704 /* top-left x */
705 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
706 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
707 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
708 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
709 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
710 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
711 s->opt[OPT_TL_X].constraint.range = &x_range;
712 s->val[OPT_TL_X].w = 0;
713
714 /* top-left y */
715 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
716 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
717 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
718 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
719 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
720 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
721 s->opt[OPT_TL_Y].constraint.range = &y_range;
722 s->val[OPT_TL_Y].w = 0;
723
724 /* bottom-right x */
725 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
726 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
727 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
728 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
729 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
730 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
731 s->opt[OPT_BR_X].constraint.range = &x_range;
732 s->val[OPT_BR_X].w = x_range.max;
733
734 /* bottom-right y */
735 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
736 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
737 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
738 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
739 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
740 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
741 s->opt[OPT_BR_Y].constraint.range = &y_range;
742 s->val[OPT_BR_Y].w = y_range.max;
743
744 /* sensor group */
745 s->opt[OPT_SENSOR_GROUP].name = SANE_NAME_SENSORS;
746 s->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS;
747 s->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS;
748 s->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP;
749 s->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
750
751 /* calibration needed */
752 s->opt[OPT_NEED_CALIBRATION_SW].name = "need-calibration";
753 s->opt[OPT_NEED_CALIBRATION_SW].title = SANE_I18N ("Needs calibration");
754 s->opt[OPT_NEED_CALIBRATION_SW].desc = SANE_I18N ("The scanner needs calibration for the current settings");
755 s->opt[OPT_NEED_CALIBRATION_SW].type = SANE_TYPE_BOOL;
756 s->opt[OPT_NEED_CALIBRATION_SW].unit = SANE_UNIT_NONE;
757 if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)
758 s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
759 else
760 s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_INACTIVE;
761 s->val[OPT_NEED_CALIBRATION_SW].b = 0;
762
763 /* document present sensor */
764 s->opt[OPT_PAGE_LOADED_SW].name = SANE_NAME_PAGE_LOADED;
765 s->opt[OPT_PAGE_LOADED_SW].title = SANE_TITLE_PAGE_LOADED;
766 s->opt[OPT_PAGE_LOADED_SW].desc = SANE_DESC_PAGE_LOADED;
767 s->opt[OPT_PAGE_LOADED_SW].type = SANE_TYPE_BOOL;
768 s->opt[OPT_PAGE_LOADED_SW].unit = SANE_UNIT_NONE;
769 if (s->dev->model->command_set->document_present)
770 s->opt[OPT_PAGE_LOADED_SW].cap =
771 SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED;
772 else
773 s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_INACTIVE;
774 s->val[OPT_PAGE_LOADED_SW].b = 0;
775
776 /* button group */
777 s->opt[OPT_BUTTON_GROUP].name = "Buttons";
778 s->opt[OPT_BUTTON_GROUP].title = SANE_I18N ("Buttons");
779 s->opt[OPT_BUTTON_GROUP].desc = SANE_I18N ("Buttons");
780 s->opt[OPT_BUTTON_GROUP].type = SANE_TYPE_GROUP;
781 s->opt[OPT_BUTTON_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
782
783 /* calibrate button */
784 s->opt[OPT_CALIBRATE].name = "calibrate";
785 s->opt[OPT_CALIBRATE].title = SANE_I18N ("Calibrate");
786 s->opt[OPT_CALIBRATE].desc =
787 SANE_I18N ("Start calibration using special sheet");
788 s->opt[OPT_CALIBRATE].type = SANE_TYPE_BUTTON;
789 s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE;
790 if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)
791 s->opt[OPT_CALIBRATE].cap =
792 SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED |
793 SANE_CAP_AUTOMATIC;
794 else
795 s->opt[OPT_CALIBRATE].cap = SANE_CAP_INACTIVE;
796 s->val[OPT_CALIBRATE].b = 0;
797
798 /* clear calibration cache button */
799 s->opt[OPT_CLEAR_CALIBRATION].name = "clear";
800 s->opt[OPT_CLEAR_CALIBRATION].title = SANE_I18N ("Clear calibration");
801 s->opt[OPT_CLEAR_CALIBRATION].desc = SANE_I18N ("Clear calibration cache");
802 s->opt[OPT_CLEAR_CALIBRATION].type = SANE_TYPE_BUTTON;
803 s->opt[OPT_CLEAR_CALIBRATION].unit = SANE_UNIT_NONE;
804 if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)
805 s->opt[OPT_CLEAR_CALIBRATION].cap =
806 SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED |
807 SANE_CAP_AUTOMATIC;
808 else
809 s->opt[OPT_CLEAR_CALIBRATION].cap = SANE_CAP_INACTIVE;
810 s->val[OPT_CLEAR_CALIBRATION].b = 0;
811
812
813 RIE (calc_parameters (s));
814
815 DBG (5, "init_options: exit\n");
816 return SANE_STATUS_GOOD;
817 }
818
819 static SANE_Status
attach(SANE_String_Const devname,GT68xx_Device ** devp,SANE_Bool may_wait)820 attach (SANE_String_Const devname, GT68xx_Device ** devp, SANE_Bool may_wait)
821 {
822 GT68xx_Device *dev;
823 SANE_Status status;
824
825 DBG (5, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==",
826 may_wait);
827 if (!devname)
828 {
829 DBG (1, "attach: devname == NULL\n");
830 return SANE_STATUS_INVAL;
831 }
832
833 for (dev = first_dev; dev; dev = dev->next)
834 {
835 if (strcmp (dev->file_name, devname) == 0)
836 {
837 if (devp)
838 *devp = dev;
839 dev->missing = SANE_FALSE;
840 DBG (4, "attach: device `%s' was already in device list\n",
841 devname);
842 return SANE_STATUS_GOOD;
843 }
844 }
845
846 DBG (4, "attach: trying to open device `%s'\n", devname);
847 RIE (gt68xx_device_new (&dev));
848 status = gt68xx_device_open (dev, devname);
849 if (status == SANE_STATUS_GOOD)
850 DBG (4, "attach: device `%s' successfully opened\n", devname);
851 else
852 {
853 DBG (4, "attach: couldn't open device `%s': %s\n", devname,
854 sane_strstatus (status));
855 gt68xx_device_free (dev);
856 if (devp)
857 *devp = 0;
858 return status;
859 }
860
861 if (!gt68xx_device_is_configured (dev))
862 {
863 GT68xx_Model *model = NULL;
864 DBG (2, "attach: Warning: device `%s' is not listed in device table\n",
865 devname);
866 DBG (2,
867 "attach: If you have manually added it, use override in gt68xx.conf\n");
868 gt68xx_device_get_model ("unknown-scanner", &model);
869 status = gt68xx_device_set_model (dev, model);
870 if (status != SANE_STATUS_GOOD)
871 {
872 DBG (4, "attach: couldn't set model: %s\n",
873 sane_strstatus (status));
874 gt68xx_device_free (dev);
875 if (devp)
876 *devp = 0;
877 return status;
878 }
879 dev->manual_selection = SANE_TRUE;
880 }
881
882 dev->file_name = strdup (devname);
883 dev->missing = SANE_FALSE;
884 if (!dev->file_name)
885 return SANE_STATUS_NO_MEM;
886 DBG (2, "attach: found %s flatbed scanner %s at %s\n", dev->model->vendor,
887 dev->model->model, dev->file_name);
888 ++num_devices;
889 dev->next = first_dev;
890 first_dev = dev;
891
892 if (devp)
893 *devp = dev;
894 gt68xx_device_close (dev);
895 DBG (5, "attach: exit\n");
896 return SANE_STATUS_GOOD;
897 }
898
899 static SANE_Status
attach_one_device(SANE_String_Const devname)900 attach_one_device (SANE_String_Const devname)
901 {
902 GT68xx_Device *dev;
903 SANE_Status status;
904
905 RIE (attach (devname, &dev, SANE_FALSE));
906
907 if (dev)
908 {
909 /* Keep track of newly attached devices so we can set options as
910 necessary. */
911 if (new_dev_len >= new_dev_alloced)
912 {
913 new_dev_alloced += 4;
914 if (new_dev)
915 new_dev =
916 realloc (new_dev, new_dev_alloced * sizeof (new_dev[0]));
917 else
918 new_dev = malloc (new_dev_alloced * sizeof (new_dev[0]));
919 if (!new_dev)
920 {
921 DBG (1, "attach_one_device: out of memory\n");
922 return SANE_STATUS_NO_MEM;
923 }
924 }
925 new_dev[new_dev_len++] = dev;
926 }
927 return SANE_STATUS_GOOD;
928 }
929
930 #if defined(_WIN32) || defined(HAVE_OS2_H)
931 # define PATH_SEP "\\"
932 #else
933 # define PATH_SEP "/"
934 #endif
935
936 static SANE_Status
download_firmware_file(GT68xx_Device * dev)937 download_firmware_file (GT68xx_Device * dev)
938 {
939 SANE_Status status = SANE_STATUS_GOOD;
940 SANE_Byte *buf = NULL;
941 int size = -1;
942 SANE_Char filename[PATH_MAX], dirname[PATH_MAX], basename[PATH_MAX];
943 FILE *f;
944
945 if (strncmp (dev->model->firmware_name, PATH_SEP, 1) != 0)
946 {
947 /* probably filename only */
948 snprintf (filename, sizeof(filename), "%s%s%s%s%s%s%s",
949 STRINGIFY (PATH_SANE_DATA_DIR),
950 PATH_SEP, "sane", PATH_SEP, "gt68xx", PATH_SEP,
951 dev->model->firmware_name);
952 snprintf (dirname, sizeof(dirname), "%s%s%s%s%s",
953 STRINGIFY (PATH_SANE_DATA_DIR),
954 PATH_SEP, "sane", PATH_SEP, "gt68xx");
955 strncpy (basename, dev->model->firmware_name, sizeof(basename) - 1);
956 basename[sizeof(basename) - 1] = '\0';
957 }
958 else
959 {
960 /* absolute path */
961 char *pos;
962 strncpy (filename, dev->model->firmware_name, sizeof(filename) - 1);
963 filename[sizeof(filename) - 1] = '\0';
964 strncpy (dirname, dev->model->firmware_name, sizeof(dirname) - 1);
965 dirname[sizeof(dirname) - 1] = '\0';
966
967 pos = strrchr (dirname, PATH_SEP[0]);
968 if (pos)
969 pos[0] = '\0';
970 strncpy (basename, pos + 1, sizeof(basename) - 1);
971 basename[sizeof(basename) - 1] = '\0';
972 }
973
974 /* first, try to open with exact case */
975 DBG (5, "download_firmware: trying %s\n", filename);
976 f = fopen (filename, "rb");
977 if (!f)
978 {
979 /* and now any case */
980 DIR *dir;
981 struct dirent *direntry;
982
983 DBG (5,
984 "download_firmware_file: Couldn't open firmware file `%s': %s\n",
985 filename, strerror (errno));
986
987 dir = opendir (dirname);
988 if (!dir)
989 {
990 DBG (5, "download_firmware: couldn't open directory `%s': %s\n",
991 dirname, strerror (errno));
992 status = SANE_STATUS_INVAL;
993 }
994 if (status == SANE_STATUS_GOOD)
995 {
996 do
997 {
998 direntry = readdir (dir);
999 if (direntry
1000 && (strncasecmp (direntry->d_name, basename, PATH_MAX) == 0))
1001 {
1002 int len = snprintf (filename, sizeof(filename), "%s%s%s",
1003 dirname, PATH_SEP, direntry->d_name);
1004 if ((len < 0) || (len >= (int) sizeof(filename)))
1005 {
1006 DBG (5, "download_firmware: filepath `%s%s%s' too long\n",
1007 dirname, PATH_SEP, direntry->d_name);
1008 status = SANE_STATUS_INVAL;
1009 }
1010 break;
1011 }
1012 }
1013 while (direntry != 0);
1014 if (direntry == 0)
1015 {
1016 DBG (5, "download_firmware: file `%s' not found\n", filename);
1017 status = SANE_STATUS_INVAL;
1018 }
1019 closedir (dir);
1020 }
1021 if (status == SANE_STATUS_GOOD)
1022 {
1023 DBG (5, "download_firmware: trying %s\n", filename);
1024 f = fopen (filename, "rb");
1025 if (!f)
1026 {
1027 DBG (5,
1028 "download_firmware_file: Couldn't open firmware file `%s': %s\n",
1029 filename, strerror (errno));
1030 status = SANE_STATUS_INVAL;
1031 }
1032 }
1033
1034 if (status != SANE_STATUS_GOOD)
1035 {
1036 DBG (0, "Couldn't open firmware file (`%s'): %s\n",
1037 filename, strerror (errno));
1038 }
1039 }
1040
1041 if (status == SANE_STATUS_GOOD)
1042 {
1043 fseek (f, 0, SEEK_END);
1044 size = ftell (f);
1045 fseek (f, 0, SEEK_SET);
1046 if (size == -1)
1047 {
1048 DBG (1, "download_firmware_file: error getting size of "
1049 "firmware file \"%s\": %s\n", filename, strerror (errno));
1050 status = SANE_STATUS_INVAL;
1051 }
1052 }
1053
1054 if (status == SANE_STATUS_GOOD)
1055 {
1056 DBG (5, "firmware size: %d\n", size);
1057 buf = (SANE_Byte *) malloc (size);
1058 if (!buf)
1059 {
1060 DBG (1, "download_firmware_file: cannot allocate %d bytes "
1061 "for firmware\n", size);
1062 status = SANE_STATUS_NO_MEM;
1063 }
1064 }
1065
1066 if (status == SANE_STATUS_GOOD)
1067 {
1068 int bytes_read = fread (buf, 1, size, f);
1069 if (bytes_read != size)
1070 {
1071 DBG (1, "download_firmware_file: problem reading firmware "
1072 "file \"%s\": %s\n", filename, strerror (errno));
1073 status = SANE_STATUS_INVAL;
1074 }
1075 }
1076
1077 if (f)
1078 fclose (f);
1079
1080 if (status == SANE_STATUS_GOOD)
1081 {
1082 status = gt68xx_device_download_firmware (dev, buf, size);
1083 if (status != SANE_STATUS_GOOD)
1084 {
1085 DBG (1, "download_firmware_file: firmware download failed: %s\n",
1086 sane_strstatus (status));
1087 }
1088 }
1089
1090 if (buf)
1091 free (buf);
1092
1093 return status;
1094 }
1095
1096 /** probe for gt68xx devices
1097 * This function scan usb and try to attached to scanner
1098 * configured in gt68xx.conf .
1099 */
probe_gt68xx_devices(void)1100 static SANE_Status probe_gt68xx_devices(void)
1101 {
1102 SANE_Char line[PATH_MAX];
1103 SANE_Char *word;
1104 SANE_String_Const cp;
1105 SANE_Int linenumber;
1106 GT68xx_Device *dev;
1107 FILE *fp;
1108
1109 /* set up for no new devices detected at first */
1110 new_dev = 0;
1111 new_dev_len = 0;
1112 new_dev_alloced = 0;
1113
1114 /* mark already detected devices as missing, during device probe
1115 * detected devices will clear this flag */
1116 dev = first_dev;
1117 while(dev!=NULL)
1118 {
1119 dev->missing = SANE_TRUE;
1120 dev = dev->next;
1121 }
1122
1123 fp = sanei_config_open (GT68XX_CONFIG_FILE);
1124 if (!fp)
1125 {
1126 /* default to /dev/usb/scanner instead of insisting on config file */
1127 DBG (3, "sane_init: couldn't open config file `%s': %s. Using "
1128 "/dev/usb/scanner directly\n", GT68XX_CONFIG_FILE,
1129 strerror (errno));
1130 attach ("/dev/usb/scanner", 0, SANE_FALSE);
1131 return SANE_STATUS_GOOD;
1132 }
1133
1134 little_endian = calc_little_endian ();
1135 DBG (5, "sane_init: %s endian machine\n", little_endian ? "little" : "big");
1136
1137 linenumber = 0;
1138 DBG (4, "sane_init: reading config file `%s'\n", GT68XX_CONFIG_FILE);
1139 while (sanei_config_read (line, sizeof (line), fp))
1140 {
1141 word = 0;
1142 linenumber++;
1143
1144 cp = sanei_config_get_string (line, &word);
1145 if (!word || cp == line)
1146 {
1147 DBG (6, "sane_init: config file line %d: ignoring empty line\n",
1148 linenumber);
1149 if (word)
1150 free (word);
1151 continue;
1152 }
1153 if (word[0] == '#')
1154 {
1155 DBG (6, "sane_init: config file line %d: ignoring comment line\n",
1156 linenumber);
1157 free (word);
1158 continue;
1159 }
1160
1161 if (strcmp (word, "firmware") == 0)
1162 {
1163 free (word);
1164 word = 0;
1165 cp = sanei_config_get_string (cp, &word);
1166 if (word)
1167 {
1168 int i;
1169 for (i = 0; i < new_dev_len; i++)
1170 {
1171 new_dev[i]->model->firmware_name = word;
1172 DBG (5, "sane_init: device %s: firmware will be loaded "
1173 "from %s\n", new_dev[i]->model->name,
1174 new_dev[i]->model->firmware_name);
1175 }
1176 if (i == 0)
1177 {
1178 DBG (5, "sane_init: firmware %s can't be loaded, set device "
1179 "first\n", word);
1180 free (word);
1181 }
1182 }
1183 else
1184 {
1185 DBG (3, "sane_init: option `firmware' needs a parameter\n");
1186 }
1187 }
1188 else if (strcmp (word, "vendor") == 0)
1189 {
1190 free (word);
1191 word = 0;
1192 cp = sanei_config_get_string (cp, &word);
1193 if (word)
1194 {
1195 int i;
1196
1197 for (i = 0; i < new_dev_len; i++)
1198 {
1199 new_dev[i]->model->vendor = word;
1200 DBG (5, "sane_init: device %s: vendor name set to %s\n",
1201 new_dev[i]->model->name, new_dev[i]->model->vendor);
1202 }
1203 if (i == 0)
1204 {
1205 DBG (5, "sane_init: can't set vendor name %s, set device "
1206 "first\n", word);
1207 free (word);
1208 }
1209 }
1210 else
1211 {
1212 DBG (3, "sane_init: option `vendor' needs a parameter\n");
1213 }
1214 }
1215 else if (strcmp (word, "model") == 0)
1216 {
1217 free (word);
1218 word = 0;
1219 cp = sanei_config_get_string (cp, &word);
1220 if (word)
1221 {
1222 int i;
1223 for (i = 0; i < new_dev_len; i++)
1224 {
1225 new_dev[i]->model->model = word;
1226 DBG (5, "sane_init: device %s: model name set to %s\n",
1227 new_dev[i]->model->name, new_dev[i]->model->model);
1228 }
1229 if (i == 0)
1230 {
1231 DBG (5, "sane_init: can't set model name %s, set device "
1232 "first\n", word);
1233 free (word);
1234 }
1235 }
1236 else
1237 {
1238 DBG (3, "sane_init: option `model' needs a parameter\n");
1239 }
1240 }
1241 else if (strcmp (word, "override") == 0)
1242 {
1243 free (word);
1244 word = 0;
1245 cp = sanei_config_get_string (cp, &word);
1246 if (word)
1247 {
1248 int i;
1249 for (i = 0; i < new_dev_len; i++)
1250 {
1251 SANE_Status status;
1252 GT68xx_Device *dev = new_dev[i];
1253 GT68xx_Model *model;
1254 if (gt68xx_device_get_model (word, &model) == SANE_TRUE)
1255 {
1256 status = gt68xx_device_set_model (dev, model);
1257 if (status != SANE_STATUS_GOOD)
1258 DBG (1, "sane_init: couldn't override model: %s\n",
1259 sane_strstatus (status));
1260 else
1261 DBG (5, "sane_init: new model set to %s\n",
1262 dev->model->name);
1263 }
1264 else
1265 {
1266 DBG (1, "sane_init: override: model %s not found\n",
1267 word);
1268 }
1269 }
1270 if (i == 0)
1271 DBG (5, "sane_init: can't override model to %s, set device "
1272 "first\n", word);
1273 free (word);
1274 }
1275 else
1276 {
1277 DBG (3, "sane_init: option `override' needs a parameter\n");
1278 }
1279 }
1280 else if (strcmp (word, "afe") == 0)
1281 {
1282 GT68xx_AFE_Parameters afe = {0, 0, 0, 0, 0, 0};
1283 SANE_Status status;
1284
1285 free (word);
1286 word = 0;
1287
1288 status = get_afe_values (cp, &afe);
1289 if (status == SANE_STATUS_GOOD)
1290 {
1291 int i;
1292 for (i = 0; i < new_dev_len; i++)
1293 {
1294 new_dev[i]->model->afe_params = afe;
1295 DBG (5, "sane_init: device %s: setting new afe values\n",
1296 new_dev[i]->model->name);
1297 }
1298 if (i == 0)
1299 DBG (5,
1300 "sane_init: can't set afe values, set device first\n");
1301 }
1302 else
1303 DBG (3, "sane_init: can't set afe values\n");
1304 }
1305 else
1306 {
1307 new_dev_len = 0;
1308 DBG (4, "sane_init: config file line %d: trying to attach `%s'\n",
1309 linenumber, line);
1310 sanei_usb_attach_matching_devices (line, attach_one_device);
1311 if (word)
1312 free (word);
1313 word = 0;
1314 }
1315 }
1316
1317 if (new_dev_alloced > 0)
1318 {
1319 new_dev_len = new_dev_alloced = 0;
1320 free (new_dev);
1321 }
1322
1323 fclose (fp);
1324 return SANE_STATUS_GOOD;
1325 }
1326
1327 /* -------------------------- SANE API functions ------------------------- */
1328
1329 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)1330 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
1331 {
1332 SANE_Status status;
1333
1334 DBG_INIT ();
1335 #ifdef DBG_LEVEL
1336 if (DBG_LEVEL > 0)
1337 {
1338 DBG (5, "sane_init: debug options are enabled, handle with care\n");
1339 debug_options = SANE_TRUE;
1340 }
1341 #endif
1342 DBG (2, "SANE GT68xx backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR,
1343 SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
1344
1345 if (version_code)
1346 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
1347
1348 DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "==");
1349
1350 sanei_usb_init ();
1351
1352 num_devices = 0;
1353 first_dev = 0;
1354 first_handle = 0;
1355 devlist = 0;
1356 new_dev = 0;
1357 new_dev_len = 0;
1358 new_dev_alloced = 0;
1359
1360 status = probe_gt68xx_devices ();
1361 DBG (5, "sane_init: exit\n");
1362
1363 return status;
1364 }
1365
1366 void
sane_exit(void)1367 sane_exit (void)
1368 {
1369 GT68xx_Device *dev, *next;
1370
1371 DBG (5, "sane_exit: start\n");
1372 sanei_usb_exit();
1373 for (dev = first_dev; dev; dev = next)
1374 {
1375 next = dev->next;
1376 gt68xx_device_free (dev);
1377 }
1378 first_dev = 0;
1379 first_handle = 0;
1380 if (devlist)
1381 free (devlist);
1382 devlist = 0;
1383
1384 DBG (5, "sane_exit: exit\n");
1385 }
1386
1387 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1388 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1389 {
1390 GT68xx_Device *dev;
1391 SANE_Int dev_num;
1392
1393 DBG (5, "sane_get_devices: start: local_only = %s\n",
1394 local_only == SANE_TRUE ? "true" : "false");
1395
1396 /* hot-plug case : detection of newly connected scanners */
1397 sanei_usb_scan_devices ();
1398 probe_gt68xx_devices ();
1399
1400 if (devlist)
1401 free (devlist);
1402
1403 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
1404 if (!devlist)
1405 return SANE_STATUS_NO_MEM;
1406
1407 dev_num = 0;
1408 dev = first_dev;
1409 while(dev!=NULL)
1410 {
1411 SANE_Device *sane_device;
1412
1413 /* don't return devices that have been unplugged */
1414 if(dev->missing==SANE_FALSE)
1415 {
1416 sane_device = malloc (sizeof (*sane_device));
1417 if (!sane_device)
1418 return SANE_STATUS_NO_MEM;
1419 sane_device->name = dev->file_name;
1420 sane_device->vendor = dev->model->vendor;
1421 sane_device->model = dev->model->model;
1422 sane_device->type = strdup ("flatbed scanner");
1423 devlist[dev_num] = sane_device;
1424 dev_num++;
1425 }
1426
1427 /* next device */
1428 dev = dev->next;
1429 }
1430 devlist[dev_num] = 0;
1431
1432 *device_list = devlist;
1433
1434 DBG (5, "sane_get_devices: exit\n");
1435
1436 return SANE_STATUS_GOOD;
1437 }
1438
1439 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)1440 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
1441 {
1442 GT68xx_Device *dev;
1443 SANE_Status status;
1444 GT68xx_Scanner *s;
1445 SANE_Bool power_ok;
1446
1447 DBG (5, "sane_open: start (devicename = `%s')\n", devicename);
1448
1449 if (devicename[0])
1450 {
1451 /* test for gt68xx short hand name */
1452 if(strcmp(devicename,"gt68xx")!=0)
1453 {
1454 for (dev = first_dev; dev; dev = dev->next)
1455 if (strcmp (dev->file_name, devicename) == 0)
1456 break;
1457
1458 if (!dev)
1459 {
1460 DBG (5, "sane_open: couldn't find `%s' in devlist, trying attach\n",
1461 devicename);
1462 RIE (attach (devicename, &dev, SANE_TRUE));
1463 }
1464 else
1465 DBG (5, "sane_open: found `%s' in devlist\n", dev->model->name);
1466 }
1467 else
1468 {
1469 dev = first_dev;
1470 if (dev)
1471 {
1472 devicename = dev->file_name;
1473 DBG (5, "sane_open: default empty devicename, using first device `%s'\n", devicename);
1474 }
1475 }
1476 }
1477 else
1478 {
1479 /* empty devicname -> use first device */
1480 dev = first_dev;
1481 if (dev)
1482 {
1483 devicename = dev->file_name;
1484 DBG (5, "sane_open: empty devicename, trying `%s'\n", devicename);
1485 }
1486 }
1487
1488 if (!dev)
1489 return SANE_STATUS_INVAL;
1490
1491 RIE (gt68xx_device_open (dev, devicename));
1492 RIE (gt68xx_device_activate (dev));
1493
1494 if (dev->model->flags & GT68XX_FLAG_UNTESTED)
1495 {
1496 DBG (0, "WARNING: Your scanner is not fully supported or at least \n");
1497 DBG (0, " had only limited testing. Please be careful and \n");
1498 DBG (0, " report any failure/success to \n");
1499 DBG (0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
1500 DBG (0, " details as possible, e.g. the exact name of your\n");
1501 DBG (0, " scanner and what does (not) work.\n");
1502 }
1503
1504 if (dev->manual_selection)
1505 {
1506 DBG (0, "WARNING: You have manually added the ids of your scanner \n");
1507 DBG (0,
1508 " to gt68xx.conf. Please use an appropriate override \n");
1509 DBG (0,
1510 " for your scanner. Use extreme care and switch off \n");
1511 DBG (0,
1512 " the scanner immediately if you hear unusual noise. \n");
1513 DBG (0, " Please report any success to \n");
1514 DBG (0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
1515 DBG (0, " details as possible, e.g. the exact name of your\n");
1516 DBG (0, " scanner, ids, settings etc.\n");
1517
1518 if (strcmp (dev->model->name, "unknown-scanner") == 0)
1519 {
1520 GT68xx_USB_Device_Entry *entry;
1521
1522 DBG (0,
1523 "ERROR: You haven't chosen an override in gt68xx.conf. Please use \n");
1524 DBG (0, " one of the following: \n");
1525
1526 for (entry = gt68xx_usb_device_list; entry->model; ++entry)
1527 {
1528 if (strcmp (entry->model->name, "unknown-scanner") != 0)
1529 DBG (0, " %s\n", entry->model->name);
1530 }
1531 return SANE_STATUS_UNSUPPORTED;
1532 }
1533 }
1534
1535 /* The firmware check is disabled by default because it may confuse
1536 some scanners: So the firmware is loaded every time. */
1537 #if 0
1538 RIE (gt68xx_device_check_firmware (dev, &firmware_loaded));
1539 firmware_loaded = SANE_FALSE;
1540 if (firmware_loaded)
1541 DBG (3, "sane_open: firmware already loaded, skipping load\n");
1542 else
1543 RIE (download_firmware_file (dev));
1544 /* RIE (gt68xx_device_check_firmware (dev, &firmware_loaded)); */
1545 if (!firmware_loaded)
1546 {
1547 DBG (1, "sane_open: firmware still not loaded? Proceeding anyway\n");
1548 /* return SANE_STATUS_IO_ERROR; */
1549 }
1550 #else
1551 RIE (download_firmware_file (dev));
1552 #endif
1553
1554 RIE (gt68xx_device_get_id (dev));
1555
1556 if (!(dev->model->flags & GT68XX_FLAG_NO_STOP))
1557 RIE (gt68xx_device_stop_scan (dev));
1558
1559 RIE (gt68xx_device_get_power_status (dev, &power_ok));
1560 if (power_ok)
1561 {
1562 DBG (5, "sane_open: power ok\n");
1563 }
1564 else
1565 {
1566 DBG (0, "sane_open: power control failure: check power plug!\n");
1567 return SANE_STATUS_IO_ERROR;
1568 }
1569
1570 RIE (gt68xx_scanner_new (dev, &s));
1571 RIE (gt68xx_device_lamp_control (s->dev, SANE_TRUE, SANE_FALSE));
1572 gettimeofday (&s->lamp_on_time, 0);
1573
1574 /* insert newly opened handle into list of open handles: */
1575 s->next = first_handle;
1576 first_handle = s;
1577 *handle = s;
1578 s->scanning = SANE_FALSE;
1579 s->first_scan = SANE_TRUE;
1580 s->gamma_table = 0;
1581 s->calibrated = SANE_FALSE;
1582 RIE (init_options (s));
1583 dev->gray_mode_color = 0x02;
1584
1585 /* try to restore calibration from file */
1586 if((s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
1587 {
1588 /* error restoring calibration is non blocking */
1589 gt68xx_read_calibration(s);
1590 }
1591
1592 DBG (5, "sane_open: exit\n");
1593
1594 return SANE_STATUS_GOOD;
1595 }
1596
1597 void
sane_close(SANE_Handle handle)1598 sane_close (SANE_Handle handle)
1599 {
1600 GT68xx_Scanner *prev, *s;
1601 GT68xx_Device *dev;
1602
1603 DBG (5, "sane_close: start\n");
1604
1605 /* remove handle from list of open handles: */
1606 prev = 0;
1607 for (s = first_handle; s; s = s->next)
1608 {
1609 if (s == handle)
1610 break;
1611 prev = s;
1612 }
1613 if (!s)
1614 {
1615 DBG (5, "close: invalid handle %p\n", handle);
1616 return; /* oops, not a handle we know about */
1617 }
1618
1619 if (prev)
1620 prev->next = s->next;
1621 else
1622 first_handle = s->next;
1623
1624 if (s->val[OPT_LAMP_OFF_AT_EXIT].w == SANE_TRUE)
1625 gt68xx_device_lamp_control (s->dev, SANE_FALSE, SANE_FALSE);
1626
1627 dev = s->dev;
1628
1629 free (s->val[OPT_MODE].s);
1630 free (s->val[OPT_GRAY_MODE_COLOR].s);
1631 free (s->val[OPT_SOURCE].s);
1632 free (dev->file_name);
1633 free ((void *)(size_t)s->opt[OPT_RESOLUTION].constraint.word_list);
1634
1635 gt68xx_scanner_free (s);
1636
1637 gt68xx_device_fix_descriptor (dev);
1638
1639 gt68xx_device_deactivate (dev);
1640 gt68xx_device_close (dev);
1641
1642 DBG (5, "sane_close: exit\n");
1643 }
1644
1645 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1646 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1647 {
1648 GT68xx_Scanner *s = handle;
1649
1650 if ((unsigned) option >= NUM_OPTIONS)
1651 return 0;
1652 DBG (5, "sane_get_option_descriptor: option = %s (%d)\n",
1653 s->opt[option].name, option);
1654 return s->opt + option;
1655 }
1656
1657 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)1658 sane_control_option (SANE_Handle handle, SANE_Int option,
1659 SANE_Action action, void *val, SANE_Int * info)
1660 {
1661 GT68xx_Scanner *s = handle;
1662 SANE_Status status = SANE_STATUS_GOOD;
1663 SANE_Word cap;
1664 SANE_Int myinfo = 0;
1665
1666 DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n",
1667 (action == SANE_ACTION_GET_VALUE) ? "get" :
1668 (action == SANE_ACTION_SET_VALUE) ? "set" :
1669 (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
1670 s->opt[option].name, option);
1671
1672 if (info)
1673 *info = 0;
1674
1675 if (s->scanning)
1676 {
1677 DBG (1, "sane_control_option: don't call this function while "
1678 "scanning (option = %s (%d))\n", s->opt[option].name, option);
1679
1680 return SANE_STATUS_DEVICE_BUSY;
1681 }
1682 if (option >= NUM_OPTIONS || option < 0)
1683 {
1684 DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n",
1685 option);
1686 return SANE_STATUS_INVAL;
1687 }
1688
1689 cap = s->opt[option].cap;
1690
1691 if (!SANE_OPTION_IS_ACTIVE (cap))
1692 {
1693 DBG (2, "sane_control_option: option %d is inactive\n", option);
1694 return SANE_STATUS_INVAL;
1695 }
1696
1697 if (action == SANE_ACTION_GET_VALUE)
1698 {
1699 switch (option)
1700 {
1701 /* word options: */
1702 case OPT_NUM_OPTS:
1703 case OPT_RESOLUTION:
1704 case OPT_BIT_DEPTH:
1705 case OPT_FULL_SCAN:
1706 case OPT_COARSE_CAL:
1707 case OPT_COARSE_CAL_ONCE:
1708 case OPT_QUALITY_CAL:
1709 case OPT_BACKTRACK:
1710 case OPT_BACKTRACK_LINES:
1711 case OPT_PREVIEW:
1712 case OPT_LAMP_OFF_AT_EXIT:
1713 case OPT_AUTO_WARMUP:
1714 case OPT_GAMMA_VALUE:
1715 case OPT_THRESHOLD:
1716 case OPT_TL_X:
1717 case OPT_TL_Y:
1718 case OPT_BR_X:
1719 case OPT_BR_Y:
1720 *(SANE_Word *) val = s->val[option].w;
1721 break;
1722 /* string options: */
1723 case OPT_MODE:
1724 case OPT_GRAY_MODE_COLOR:
1725 case OPT_SOURCE:
1726 strcpy (val, s->val[option].s);
1727 break;
1728 case OPT_NEED_CALIBRATION_SW:
1729 *(SANE_Bool *) val = !s->calibrated;
1730 break;
1731 case OPT_PAGE_LOADED_SW:
1732 s->dev->model->command_set->document_present (s->dev, val);
1733 break;
1734 default:
1735 DBG (2, "sane_control_option: can't get unknown option %d\n",
1736 option);
1737 }
1738 }
1739 else if (action == SANE_ACTION_SET_VALUE)
1740 {
1741 if (!SANE_OPTION_IS_SETTABLE (cap))
1742 {
1743 DBG (2, "sane_control_option: option %d is not settable\n", option);
1744 return SANE_STATUS_INVAL;
1745 }
1746
1747 status = sanei_constrain_value (s->opt + option, val, &myinfo);
1748
1749 if (status != SANE_STATUS_GOOD)
1750 {
1751 DBG (2, "sane_control_option: sanei_constrain_value returned %s\n",
1752 sane_strstatus (status));
1753 return status;
1754 }
1755
1756 switch (option)
1757 {
1758 case OPT_RESOLUTION:
1759 case OPT_BIT_DEPTH:
1760 case OPT_FULL_SCAN:
1761 case OPT_PREVIEW:
1762 case OPT_TL_X:
1763 case OPT_TL_Y:
1764 case OPT_BR_X:
1765 case OPT_BR_Y:
1766 s->val[option].w = *(SANE_Word *) val;
1767 RIE (calc_parameters (s));
1768 myinfo |= SANE_INFO_RELOAD_PARAMS;
1769 break;
1770 case OPT_LAMP_OFF_AT_EXIT:
1771 case OPT_AUTO_WARMUP:
1772 case OPT_COARSE_CAL_ONCE:
1773 case OPT_BACKTRACK_LINES:
1774 case OPT_QUALITY_CAL:
1775 case OPT_GAMMA_VALUE:
1776 case OPT_THRESHOLD:
1777 s->val[option].w = *(SANE_Word *) val;
1778 break;
1779 case OPT_GRAY_MODE_COLOR:
1780 if (strcmp (s->val[option].s, val) != 0)
1781 { /* something changed */
1782 if (s->val[option].s)
1783 free (s->val[option].s);
1784 s->val[option].s = strdup (val);
1785 }
1786 break;
1787 case OPT_SOURCE:
1788 if (strcmp (s->val[option].s, val) != 0)
1789 { /* something changed */
1790 if (s->val[option].s)
1791 free (s->val[option].s);
1792 s->val[option].s = strdup (val);
1793 if (strcmp (s->val[option].s, "Transparency Adapter") == 0)
1794 {
1795 RIE (gt68xx_device_lamp_control
1796 (s->dev, SANE_FALSE, SANE_TRUE));
1797 x_range.max = s->dev->model->x_size_ta;
1798 y_range.max = s->dev->model->y_size_ta;
1799 }
1800 else
1801 {
1802 RIE (gt68xx_device_lamp_control
1803 (s->dev, SANE_TRUE, SANE_FALSE));
1804 x_range.max = s->dev->model->x_size;
1805 y_range.max = s->dev->model->y_size;
1806 }
1807 s->first_scan = SANE_TRUE;
1808 myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1809 gettimeofday (&s->lamp_on_time, 0);
1810 }
1811 break;
1812 case OPT_MODE:
1813 if (s->val[option].s)
1814 free (s->val[option].s);
1815 s->val[option].s = strdup (val);
1816 if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
1817 {
1818 ENABLE (OPT_THRESHOLD);
1819 DISABLE (OPT_BIT_DEPTH);
1820 ENABLE (OPT_GRAY_MODE_COLOR);
1821 }
1822 else
1823 {
1824 DISABLE (OPT_THRESHOLD);
1825 if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
1826 {
1827 RIE (create_bpp_list (s, s->dev->model->bpp_gray_values));
1828 ENABLE (OPT_GRAY_MODE_COLOR);
1829 }
1830 else
1831 {
1832 RIE (create_bpp_list (s, s->dev->model->bpp_color_values));
1833 DISABLE (OPT_GRAY_MODE_COLOR);
1834 }
1835 if (s->bpp_list[0] < 2)
1836 DISABLE (OPT_BIT_DEPTH);
1837 else
1838 ENABLE (OPT_BIT_DEPTH);
1839 }
1840 RIE (calc_parameters (s));
1841 myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1842 break;
1843
1844 case OPT_COARSE_CAL:
1845 s->val[option].w = *(SANE_Word *) val;
1846 if (s->val[option].w == SANE_TRUE)
1847 {
1848 ENABLE (OPT_COARSE_CAL_ONCE);
1849 s->first_scan = SANE_TRUE;
1850 }
1851 else
1852 {
1853 DISABLE (OPT_COARSE_CAL_ONCE);
1854 }
1855 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1856 break;
1857
1858 case OPT_BACKTRACK:
1859 s->val[option].w = *(SANE_Word *) val;
1860 if (s->val[option].w == SANE_TRUE)
1861 ENABLE (OPT_BACKTRACK_LINES);
1862 else
1863 DISABLE (OPT_BACKTRACK_LINES);
1864 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1865 break;
1866
1867 case OPT_CALIBRATE:
1868 status = gt68xx_sheetfed_scanner_calibrate (s);
1869 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1870 break;
1871
1872 case OPT_CLEAR_CALIBRATION:
1873 gt68xx_clear_calibration (s);
1874 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1875 break;
1876
1877 default:
1878 DBG (2, "sane_control_option: can't set unknown option %d\n",
1879 option);
1880 }
1881 }
1882 else
1883 {
1884 DBG (2, "sane_control_option: unknown action %d for option %d\n",
1885 action, option);
1886 return SANE_STATUS_INVAL;
1887 }
1888 if (info)
1889 *info = myinfo;
1890
1891 DBG (5, "sane_control_option: exit\n");
1892 return status;
1893 }
1894
1895 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1896 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1897 {
1898 GT68xx_Scanner *s = handle;
1899 SANE_Status status;
1900
1901 DBG (5, "sane_get_parameters: start\n");
1902
1903 RIE (calc_parameters (s));
1904 if (params)
1905 *params = s->params;
1906
1907 DBG (4, "sane_get_parameters: format=%d, last_frame=%d, lines=%d\n",
1908 s->params.format, s->params.last_frame, s->params.lines);
1909 DBG (4, "sane_get_parameters: pixels_per_line=%d, bytes per line=%d\n",
1910 s->params.pixels_per_line, s->params.bytes_per_line);
1911 DBG (3, "sane_get_parameters: pixels %dx%dx%d\n",
1912 s->params.pixels_per_line, s->params.lines, 1 << s->params.depth);
1913
1914 DBG (5, "sane_get_parameters: exit\n");
1915
1916 return SANE_STATUS_GOOD;
1917 }
1918
1919 SANE_Status
sane_start(SANE_Handle handle)1920 sane_start (SANE_Handle handle)
1921 {
1922 GT68xx_Scanner *s = handle;
1923 GT68xx_Scan_Request scan_request;
1924 GT68xx_Scan_Parameters scan_params;
1925 SANE_Status status;
1926 SANE_Int i, gamma_size;
1927 unsigned int *buffer_pointers[3];
1928 SANE_Bool document;
1929
1930 DBG (5, "sane_start: start\n");
1931
1932 /* First make sure we have a current parameter set. Some of the
1933 parameters will be overwritten below, but that's OK. */
1934 RIE (calc_parameters (s));
1935
1936 if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w)
1937 {
1938 DBG (0, "sane_start: top left x >= bottom right x --- exiting\n");
1939 return SANE_STATUS_INVAL;
1940 }
1941 if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w)
1942 {
1943 DBG (0, "sane_start: top left y >= bottom right y --- exiting\n");
1944 return SANE_STATUS_INVAL;
1945 }
1946
1947 if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_BLUE) == 0)
1948 s->dev->gray_mode_color = 0x01;
1949 else if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_GREEN) == 0)
1950 s->dev->gray_mode_color = 0x02;
1951 else
1952 s->dev->gray_mode_color = 0x03;
1953
1954 setup_scan_request (s, &scan_request);
1955 if (!s->first_scan && s->val[OPT_COARSE_CAL_ONCE].w == SANE_TRUE)
1956 s->auto_afe = SANE_FALSE;
1957 else
1958 s->auto_afe = s->val[OPT_COARSE_CAL].w;
1959
1960 s->dev->gamma_value = s->val[OPT_GAMMA_VALUE].w;
1961 gamma_size = s->params.depth == 16 ? 65536 : 256;
1962 s->gamma_table = malloc (sizeof (SANE_Int) * gamma_size);
1963 if (!s->gamma_table)
1964 {
1965 DBG (1, "sane_start: couldn't malloc %d bytes for gamma table\n",
1966 gamma_size);
1967 return SANE_STATUS_NO_MEM;
1968 }
1969 for (i = 0; i < gamma_size; i++)
1970 {
1971 s->gamma_table[i] =
1972 (gamma_size - 1) * pow (((double) i + 1) / (gamma_size),
1973 1.0 / SANE_UNFIX (s->dev->gamma_value)) + 0.5;
1974 if (s->gamma_table[i] > (gamma_size - 1))
1975 s->gamma_table[i] = (gamma_size - 1);
1976 if (s->gamma_table[i] < 0)
1977 s->gamma_table[i] = 0;
1978 #if 0
1979 printf ("%d %d\n", i, s->gamma_table[i]);
1980 #endif
1981 }
1982
1983 if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
1984 {
1985 s->calib = s->val[OPT_QUALITY_CAL].w;
1986 }
1987
1988 if (!(s->dev->model->flags & GT68XX_FLAG_NO_STOP))
1989 RIE (gt68xx_device_stop_scan (s->dev));
1990
1991 if (!(s->dev->model->flags & GT68XX_FLAG_SHEET_FED))
1992 RIE (gt68xx_device_carriage_home (s->dev));
1993
1994 gt68xx_scanner_wait_for_positioning (s);
1995 gettimeofday (&s->start_time, 0);
1996
1997 if (s->val[OPT_BACKTRACK].w == SANE_TRUE)
1998 scan_request.backtrack = SANE_TRUE;
1999 else
2000 {
2001 if (s->val[OPT_RESOLUTION].w >= s->dev->model->ydpi_no_backtrack)
2002 scan_request.backtrack = SANE_FALSE;
2003 else
2004 scan_request.backtrack = SANE_TRUE;
2005 }
2006
2007 if (scan_request.backtrack)
2008 scan_request.backtrack_lines = s->val[OPT_BACKTRACK_LINES].w;
2009 else
2010 scan_request.backtrack_lines = 0;
2011
2012 /* don't call calibration for scanners that use sheetfed_calibrate */
2013 if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
2014 {
2015 RIE (gt68xx_scanner_calibrate (s, &scan_request));
2016 }
2017 else
2018 {
2019 s->calib = s->calibrated;
2020 }
2021
2022 /* is possible, wait for document to be inserted before scanning */
2023 /* wait for 5 secondes max */
2024 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED
2025 && s->dev->model->command_set->document_present)
2026 {
2027 i=0;
2028 do
2029 {
2030 RIE(s->dev->model->command_set->document_present(s->dev,&document));
2031 if(document==SANE_FALSE)
2032 {
2033 i++;
2034 sleep(1);
2035 }
2036 } while ((i<5) && (document==SANE_FALSE));
2037 if(document==SANE_FALSE)
2038 {
2039 DBG (4, "sane_start: no document detected after %d s\n",i);
2040 return SANE_STATUS_NO_DOCS;
2041 }
2042 }
2043
2044 /* some sheetfed scanners need a special operation to move
2045 * paper before starting real scan */
2046 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
2047 {
2048 RIE (gt68xx_sheetfed_move_to_scan_area (s, &scan_request));
2049 }
2050
2051 /* restore calibration */
2052 if( (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)
2053 &&(s->calibrated == SANE_TRUE))
2054 {
2055 /* compute scan parameters */
2056 scan_request.calculate = SANE_TRUE;
2057 gt68xx_device_setup_scan (s->dev, &scan_request, SA_SCAN, &scan_params);
2058
2059 /* restore settings from calibration stored */
2060 memcpy(s->dev->afe,&(s->afe_params), sizeof(GT68xx_AFE_Parameters));
2061 RIE (gt68xx_assign_calibration (s, scan_params));
2062 scan_request.calculate = SANE_FALSE;
2063 }
2064
2065 /* send scan request to the scanner */
2066 RIE (gt68xx_scanner_start_scan (s, &scan_request, &scan_params));
2067
2068 for (i = 0; i < scan_params.overscan_lines; ++i)
2069 RIE (gt68xx_scanner_read_line (s, buffer_pointers));
2070 DBG (4, "sane_start: wanted: dpi=%d, x=%.1f, y=%.1f, width=%.1f, "
2071 "height=%.1f, color=%s\n", scan_request.xdpi,
2072 SANE_UNFIX (scan_request.x0),
2073 SANE_UNFIX (scan_request.y0), SANE_UNFIX (scan_request.xs),
2074 SANE_UNFIX (scan_request.ys), scan_request.color ? "color" : "gray");
2075
2076 s->line = 0;
2077 s->byte_count = s->reader->params.pixel_xs;
2078 s->total_bytes = 0;
2079 s->first_scan = SANE_FALSE;
2080
2081 #ifdef DEBUG_BRIGHTNESS
2082 s->average_white = 0;
2083 s->max_white = 0;
2084 s->min_black = 255;
2085 #endif
2086
2087 s->scanning = SANE_TRUE;
2088
2089 DBG (5, "sane_start: exit\n");
2090 return SANE_STATUS_GOOD;
2091 }
2092
2093 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)2094 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2095 SANE_Int * len)
2096 {
2097 GT68xx_Scanner *s = handle;
2098 SANE_Status status;
2099 static unsigned int *buffer_pointers[3];
2100 SANE_Int inflate_x;
2101 SANE_Bool lineart;
2102 SANE_Int i, color, colors;
2103
2104 if (!s)
2105 {
2106 DBG (1, "sane_read: handle is null!\n");
2107 return SANE_STATUS_INVAL;
2108 }
2109
2110 if (!buf)
2111 {
2112 DBG (1, "sane_read: buf is null!\n");
2113 return SANE_STATUS_INVAL;
2114 }
2115
2116 if (!len)
2117 {
2118 DBG (1, "sane_read: len is null!\n");
2119 return SANE_STATUS_INVAL;
2120 }
2121
2122 *len = 0;
2123
2124 if (!s->scanning)
2125 {
2126 DBG (3, "sane_read: scan was cancelled, is over or has not been "
2127 "initiated yet\n");
2128 return SANE_STATUS_CANCELLED;
2129 }
2130
2131 DBG (5, "sane_read: start (line %d of %d, byte_count %d of %d)\n",
2132 s->line, s->reader->params.pixel_ys, s->byte_count,
2133 s->reader->params.pixel_xs);
2134
2135 if (s->line >= s->reader->params.pixel_ys
2136 && s->byte_count >= s->reader->params.pixel_xs)
2137 {
2138 DBG (4, "sane_read: nothing more to scan: EOF\n");
2139 gt68xx_scanner_stop_scan(s);
2140 return SANE_STATUS_EOF;
2141 }
2142
2143 inflate_x = s->val[OPT_RESOLUTION].w / s->dev->model->optical_xdpi;
2144 if (inflate_x > 1)
2145 DBG (5, "sane_read: inflating x by factor %d\n", inflate_x);
2146 else
2147 inflate_x = 1;
2148
2149 lineart = (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
2150 ? SANE_TRUE : SANE_FALSE;
2151
2152 if (s->reader->params.color)
2153 colors = 3;
2154 else
2155 colors = 1;
2156
2157 while ((*len) < max_len)
2158 {
2159 if (s->byte_count >= s->reader->params.pixel_xs)
2160 {
2161 if (s->line >= s->reader->params.pixel_ys)
2162 {
2163 DBG (4, "sane_read: scan complete: %d bytes, %d total\n",
2164 *len, s->total_bytes);
2165 return SANE_STATUS_GOOD;
2166 }
2167 DBG (5, "sane_read: getting line %d of %d\n", s->line,
2168 s->reader->params.pixel_ys);
2169 RIE (gt68xx_scanner_read_line (s, buffer_pointers));
2170 s->line++;
2171 s->byte_count = 0;
2172
2173 /* Apply gamma */
2174 for (color = 0; color < colors; color++)
2175 for (i = 0; i < s->reader->pixels_per_line; i++)
2176 {
2177 if (s->reader->params.depth > 8)
2178 buffer_pointers[color][i] =
2179 s->gamma_table[buffer_pointers[color][i]];
2180 else
2181 buffer_pointers[color][i] =
2182 (s->gamma_table[buffer_pointers[color][i] >> 8] << 8) +
2183 (s->gamma_table[buffer_pointers[color][i] >> 8]);
2184 }
2185 /* mirror lines */
2186 if (s->dev->model->flags & GT68XX_FLAG_MIRROR_X)
2187 {
2188 unsigned int swap;
2189
2190 for (color = 0; color < colors; color++)
2191 {
2192 for (i = 0; i < s->reader->pixels_per_line / 2; i++)
2193 {
2194 swap = buffer_pointers[color][i];
2195 buffer_pointers[color][i] =
2196 buffer_pointers[color][s->reader->pixels_per_line -
2197 1 - i];
2198 buffer_pointers[color][s->reader->pixels_per_line - 1 -
2199 i] = swap;
2200 }
2201 }
2202 }
2203 }
2204 if (lineart)
2205 {
2206 SANE_Int bit;
2207 SANE_Byte threshold = s->val[OPT_THRESHOLD].w;
2208
2209 buf[*len] = 0;
2210 for (bit = 7; bit >= 0; bit--)
2211 {
2212 SANE_Byte is_black =
2213 (((buffer_pointers[0][s->byte_count] >> 8) & 0xff) >
2214 threshold) ? 0 : 1;
2215 buf[*len] |= (is_black << bit);
2216 if ((7 - bit) % inflate_x == (inflate_x - 1))
2217 s->byte_count++;
2218 }
2219 }
2220 else if (s->reader->params.color)
2221 {
2222 /* color */
2223 if (s->reader->params.depth > 8)
2224 {
2225 SANE_Int color = (s->total_bytes / 2) % 3;
2226 if ((s->total_bytes % 2) == 0)
2227 {
2228 if (little_endian)
2229 buf[*len] = buffer_pointers[color][s->byte_count] & 0xff;
2230 else
2231 buf[*len] =
2232 (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2233 }
2234 else
2235 {
2236 if (little_endian)
2237 buf[*len] =
2238 (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2239 else
2240 buf[*len] = buffer_pointers[color][s->byte_count] & 0xff;
2241
2242 if (s->total_bytes % (inflate_x * 6) == (inflate_x * 6 - 1))
2243 s->byte_count++;
2244 }
2245 }
2246 else
2247 {
2248 SANE_Int color = s->total_bytes % 3;
2249 buf[*len] = (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2250 if (s->total_bytes % (inflate_x * 3) == (inflate_x * 3 - 1))
2251 s->byte_count++;
2252 #ifdef DEBUG_BRIGHTNESS
2253 s->average_white += buf[*len];
2254 s->max_white =
2255 (buf[*len] > s->max_white) ? buf[*len] : s->max_white;
2256 s->min_black =
2257 (buf[*len] < s->min_black) ? buf[*len] : s->min_black;
2258 #endif
2259 }
2260 }
2261 else
2262 {
2263 /* gray */
2264 if (s->reader->params.depth > 8)
2265 {
2266 if ((s->total_bytes % 2) == 0)
2267 {
2268 if (little_endian)
2269 buf[*len] = buffer_pointers[0][s->byte_count] & 0xff;
2270 else
2271 buf[*len] =
2272 (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2273 }
2274 else
2275 {
2276 if (little_endian)
2277 buf[*len] =
2278 (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2279 else
2280 buf[*len] = buffer_pointers[0][s->byte_count] & 0xff;
2281 if (s->total_bytes % (2 * inflate_x) == (2 * inflate_x - 1))
2282 s->byte_count++;
2283 }
2284 }
2285 else
2286 {
2287 buf[*len] = (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2288 if (s->total_bytes % inflate_x == (inflate_x - 1))
2289 s->byte_count++;
2290 }
2291 }
2292 (*len)++;
2293 s->total_bytes++;
2294 }
2295
2296 DBG (4, "sane_read: exit (line %d of %d, byte_count %d of %d, %d bytes, "
2297 "%d total)\n",
2298 s->line, s->reader->params.pixel_ys, s->byte_count,
2299 s->reader->params.pixel_xs, *len, s->total_bytes);
2300 return SANE_STATUS_GOOD;
2301 }
2302
2303 void
sane_cancel(SANE_Handle handle)2304 sane_cancel (SANE_Handle handle)
2305 {
2306 GT68xx_Scanner *s = handle;
2307
2308 DBG (5, "sane_cancel: start\n");
2309
2310 if (s->scanning)
2311 {
2312 s->scanning = SANE_FALSE;
2313 if (s->total_bytes != (s->params.bytes_per_line * s->params.lines))
2314 DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d "
2315 "bytes\n", s->total_bytes,
2316 s->params.bytes_per_line * s->params.lines);
2317 else
2318 {
2319 struct timeval now;
2320 int secs;
2321
2322 gettimeofday (&now, 0);
2323 secs = now.tv_sec - s->start_time.tv_sec;
2324
2325 DBG (3,
2326 "sane_cancel: scan finished, scanned %d bytes in %d seconds\n",
2327 s->total_bytes, secs);
2328 #ifdef DEBUG_BRIGHTNESS
2329 DBG (1,
2330 "sane_cancel: average white: %d, max_white=%d, min_black=%d\n",
2331 s->average_white / s->total_bytes, s->max_white, s->min_black);
2332 #endif
2333
2334 }
2335 /* some scanners don't like this command when cancelling a scan */
2336 sanei_usb_set_timeout (SHORT_TIMEOUT);
2337 gt68xx_device_fix_descriptor (s->dev);
2338 gt68xx_scanner_stop_scan (s);
2339 sanei_usb_set_timeout (LONG_TIMEOUT);
2340
2341 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
2342 {
2343 gt68xx_device_paperfeed (s->dev);
2344 }
2345 else
2346 {
2347 sanei_usb_set_timeout (SHORT_TIMEOUT);
2348 gt68xx_scanner_wait_for_positioning (s);
2349 sanei_usb_set_timeout (LONG_TIMEOUT);
2350 gt68xx_device_carriage_home (s->dev);
2351 }
2352 if (s->gamma_table)
2353 {
2354 free (s->gamma_table);
2355 s->gamma_table = 0;
2356 }
2357 }
2358 else
2359 {
2360 DBG (4, "sane_cancel: scan has not been initiated yet, "
2361 "or it is already aborted\n");
2362 }
2363
2364 DBG (5, "sane_cancel: exit\n");
2365 return;
2366 }
2367
2368 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)2369 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2370 {
2371 GT68xx_Scanner *s = handle;
2372
2373 DBG (5, "sane_set_io_mode: handle = %p, non_blocking = %s\n",
2374 handle, non_blocking == SANE_TRUE ? "true" : "false");
2375
2376 if (!s->scanning)
2377 {
2378 DBG (1, "sane_set_io_mode: not scanning\n");
2379 return SANE_STATUS_INVAL;
2380 }
2381 if (non_blocking)
2382 return SANE_STATUS_UNSUPPORTED;
2383 return SANE_STATUS_GOOD;
2384 }
2385
2386 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)2387 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2388 {
2389 GT68xx_Scanner *s = handle;
2390
2391 DBG (5, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd);
2392
2393 if (!s->scanning)
2394 {
2395 DBG (1, "sane_get_select_fd: not scanning\n");
2396 return SANE_STATUS_INVAL;
2397 }
2398 return SANE_STATUS_UNSUPPORTED;
2399 }
2400
2401 /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
2402