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 DBG (5, "sane_init: firmware %s can't be loaded, set device "
1178 "first\n", word);
1179 }
1180 else
1181 {
1182 DBG (3, "sane_init: option `firmware' needs a parameter\n");
1183 }
1184 }
1185 else if (strcmp (word, "vendor") == 0)
1186 {
1187 free (word);
1188 word = 0;
1189 cp = sanei_config_get_string (cp, &word);
1190 if (word)
1191 {
1192 int i;
1193
1194 for (i = 0; i < new_dev_len; i++)
1195 {
1196 new_dev[i]->model->vendor = word;
1197 DBG (5, "sane_init: device %s: vendor name set to %s\n",
1198 new_dev[i]->model->name, new_dev[i]->model->vendor);
1199 }
1200 if (i == 0)
1201 DBG (5, "sane_init: can't set vendor name %s, set device "
1202 "first\n", word);
1203 }
1204 else
1205 {
1206 DBG (3, "sane_init: option `vendor' needs a parameter\n");
1207 }
1208 }
1209 else if (strcmp (word, "model") == 0)
1210 {
1211 free (word);
1212 word = 0;
1213 cp = sanei_config_get_string (cp, &word);
1214 if (word)
1215 {
1216 int i;
1217 for (i = 0; i < new_dev_len; i++)
1218 {
1219 new_dev[i]->model->model = word;
1220 DBG (5, "sane_init: device %s: model name set to %s\n",
1221 new_dev[i]->model->name, new_dev[i]->model->model);
1222 }
1223 if (i == 0)
1224 DBG (5, "sane_init: can't set model name %s, set device "
1225 "first\n", word);
1226 free (word);
1227 }
1228 else
1229 {
1230 DBG (3, "sane_init: option `model' needs a parameter\n");
1231 }
1232 }
1233 else if (strcmp (word, "override") == 0)
1234 {
1235 free (word);
1236 word = 0;
1237 cp = sanei_config_get_string (cp, &word);
1238 if (word)
1239 {
1240 int i;
1241 for (i = 0; i < new_dev_len; i++)
1242 {
1243 SANE_Status status;
1244 GT68xx_Device *dev = new_dev[i];
1245 GT68xx_Model *model;
1246 if (gt68xx_device_get_model (word, &model) == SANE_TRUE)
1247 {
1248 status = gt68xx_device_set_model (dev, model);
1249 if (status != SANE_STATUS_GOOD)
1250 DBG (1, "sane_init: couldn't override model: %s\n",
1251 sane_strstatus (status));
1252 else
1253 DBG (5, "sane_init: new model set to %s\n",
1254 dev->model->name);
1255 }
1256 else
1257 {
1258 DBG (1, "sane_init: override: model %s not found\n",
1259 word);
1260 }
1261 }
1262 if (i == 0)
1263 DBG (5, "sane_init: can't override model to %s, set device "
1264 "first\n", word);
1265 free (word);
1266 }
1267 else
1268 {
1269 DBG (3, "sane_init: option `override' needs a parameter\n");
1270 }
1271 }
1272 else if (strcmp (word, "afe") == 0)
1273 {
1274 GT68xx_AFE_Parameters afe = {0, 0, 0, 0, 0, 0};
1275 SANE_Status status;
1276
1277 free (word);
1278 word = 0;
1279
1280 status = get_afe_values (cp, &afe);
1281 if (status == SANE_STATUS_GOOD)
1282 {
1283 int i;
1284 for (i = 0; i < new_dev_len; i++)
1285 {
1286 new_dev[i]->model->afe_params = afe;
1287 DBG (5, "sane_init: device %s: setting new afe values\n",
1288 new_dev[i]->model->name);
1289 }
1290 if (i == 0)
1291 DBG (5,
1292 "sane_init: can't set afe values, set device first\n");
1293 }
1294 else
1295 DBG (3, "sane_init: can't set afe values\n");
1296 }
1297 else
1298 {
1299 new_dev_len = 0;
1300 DBG (4, "sane_init: config file line %d: trying to attach `%s'\n",
1301 linenumber, line);
1302 sanei_usb_attach_matching_devices (line, attach_one_device);
1303 if (word)
1304 free (word);
1305 word = 0;
1306 }
1307 }
1308
1309 if (new_dev_alloced > 0)
1310 {
1311 new_dev_len = new_dev_alloced = 0;
1312 free (new_dev);
1313 }
1314
1315 fclose (fp);
1316 return SANE_STATUS_GOOD;
1317 }
1318
1319 /* -------------------------- SANE API functions ------------------------- */
1320
1321 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)1322 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
1323 {
1324 SANE_Status status;
1325
1326 DBG_INIT ();
1327 #ifdef DBG_LEVEL
1328 if (DBG_LEVEL > 0)
1329 {
1330 DBG (5, "sane_init: debug options are enabled, handle with care\n");
1331 debug_options = SANE_TRUE;
1332 }
1333 #endif
1334 DBG (2, "SANE GT68xx backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR,
1335 V_MINOR, BUILD, PACKAGE_STRING);
1336
1337 if (version_code)
1338 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD);
1339
1340 DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "==");
1341
1342 sanei_usb_init ();
1343
1344 num_devices = 0;
1345 first_dev = 0;
1346 first_handle = 0;
1347 devlist = 0;
1348 new_dev = 0;
1349 new_dev_len = 0;
1350 new_dev_alloced = 0;
1351
1352 status = probe_gt68xx_devices ();
1353 DBG (5, "sane_init: exit\n");
1354
1355 return status;
1356 }
1357
1358 void
sane_exit(void)1359 sane_exit (void)
1360 {
1361 GT68xx_Device *dev, *next;
1362
1363 DBG (5, "sane_exit: start\n");
1364 sanei_usb_exit();
1365 for (dev = first_dev; dev; dev = next)
1366 {
1367 next = dev->next;
1368 gt68xx_device_free (dev);
1369 }
1370 first_dev = 0;
1371 first_handle = 0;
1372 if (devlist)
1373 free (devlist);
1374 devlist = 0;
1375
1376 DBG (5, "sane_exit: exit\n");
1377 }
1378
1379 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1380 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1381 {
1382 GT68xx_Device *dev;
1383 SANE_Int dev_num;
1384
1385 DBG (5, "sane_get_devices: start: local_only = %s\n",
1386 local_only == SANE_TRUE ? "true" : "false");
1387
1388 /* hot-plug case : detection of newly connected scanners */
1389 sanei_usb_scan_devices ();
1390 probe_gt68xx_devices ();
1391
1392 if (devlist)
1393 free (devlist);
1394
1395 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
1396 if (!devlist)
1397 return SANE_STATUS_NO_MEM;
1398
1399 dev_num = 0;
1400 dev = first_dev;
1401 while(dev!=NULL)
1402 {
1403 SANE_Device *sane_device;
1404
1405 /* don't return devices that have been unplugged */
1406 if(dev->missing==SANE_FALSE)
1407 {
1408 sane_device = malloc (sizeof (*sane_device));
1409 if (!sane_device)
1410 return SANE_STATUS_NO_MEM;
1411 sane_device->name = dev->file_name;
1412 sane_device->vendor = dev->model->vendor;
1413 sane_device->model = dev->model->model;
1414 sane_device->type = strdup ("flatbed scanner");
1415 devlist[dev_num] = sane_device;
1416 dev_num++;
1417 }
1418
1419 /* next device */
1420 dev = dev->next;
1421 }
1422 devlist[dev_num] = 0;
1423
1424 *device_list = devlist;
1425
1426 DBG (5, "sane_get_devices: exit\n");
1427
1428 return SANE_STATUS_GOOD;
1429 }
1430
1431 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)1432 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
1433 {
1434 GT68xx_Device *dev;
1435 SANE_Status status;
1436 GT68xx_Scanner *s;
1437 SANE_Bool power_ok;
1438
1439 DBG (5, "sane_open: start (devicename = `%s')\n", devicename);
1440
1441 if (devicename[0])
1442 {
1443 /* test for gt68xx short hand name */
1444 if(strcmp(devicename,"gt68xx")!=0)
1445 {
1446 for (dev = first_dev; dev; dev = dev->next)
1447 if (strcmp (dev->file_name, devicename) == 0)
1448 break;
1449
1450 if (!dev)
1451 {
1452 DBG (5, "sane_open: couldn't find `%s' in devlist, trying attach\n",
1453 devicename);
1454 RIE (attach (devicename, &dev, SANE_TRUE));
1455 }
1456 else
1457 DBG (5, "sane_open: found `%s' in devlist\n", dev->model->name);
1458 }
1459 else
1460 {
1461 dev = first_dev;
1462 if (dev)
1463 {
1464 devicename = dev->file_name;
1465 DBG (5, "sane_open: default empty devicename, using first device `%s'\n", devicename);
1466 }
1467 }
1468 }
1469 else
1470 {
1471 /* empty devicname -> use first device */
1472 dev = first_dev;
1473 if (dev)
1474 {
1475 devicename = dev->file_name;
1476 DBG (5, "sane_open: empty devicename, trying `%s'\n", devicename);
1477 }
1478 }
1479
1480 if (!dev)
1481 return SANE_STATUS_INVAL;
1482
1483 RIE (gt68xx_device_open (dev, devicename));
1484 RIE (gt68xx_device_activate (dev));
1485
1486 if (dev->model->flags & GT68XX_FLAG_UNTESTED)
1487 {
1488 DBG (0, "WARNING: Your scanner is not fully supported or at least \n");
1489 DBG (0, " had only limited testing. Please be careful and \n");
1490 DBG (0, " report any failure/success to \n");
1491 DBG (0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
1492 DBG (0, " details as possible, e.g. the exact name of your\n");
1493 DBG (0, " scanner and what does (not) work.\n");
1494 }
1495
1496 if (dev->manual_selection)
1497 {
1498 DBG (0, "WARNING: You have manually added the ids of your scanner \n");
1499 DBG (0,
1500 " to gt68xx.conf. Please use an appropriate override \n");
1501 DBG (0,
1502 " for your scanner. Use extreme care and switch off \n");
1503 DBG (0,
1504 " the scanner immediately if you hear unusual noise. \n");
1505 DBG (0, " Please report any success to \n");
1506 DBG (0, " sane-devel@alioth-lists.debian.net. Please provide as many\n");
1507 DBG (0, " details as possible, e.g. the exact name of your\n");
1508 DBG (0, " scanner, ids, settings etc.\n");
1509
1510 if (strcmp (dev->model->name, "unknown-scanner") == 0)
1511 {
1512 GT68xx_USB_Device_Entry *entry;
1513
1514 DBG (0,
1515 "ERROR: You haven't chosen an override in gt68xx.conf. Please use \n");
1516 DBG (0, " one of the following: \n");
1517
1518 for (entry = gt68xx_usb_device_list; entry->model; ++entry)
1519 {
1520 if (strcmp (entry->model->name, "unknown-scanner") != 0)
1521 DBG (0, " %s\n", entry->model->name);
1522 }
1523 return SANE_STATUS_UNSUPPORTED;
1524 }
1525 }
1526
1527 /* The firmware check is disabled by default because it may confuse
1528 some scanners: So the firmware is loaded every time. */
1529 #if 0
1530 RIE (gt68xx_device_check_firmware (dev, &firmware_loaded));
1531 firmware_loaded = SANE_FALSE;
1532 if (firmware_loaded)
1533 DBG (3, "sane_open: firmware already loaded, skipping load\n");
1534 else
1535 RIE (download_firmware_file (dev));
1536 /* RIE (gt68xx_device_check_firmware (dev, &firmware_loaded)); */
1537 if (!firmware_loaded)
1538 {
1539 DBG (1, "sane_open: firmware still not loaded? Proceeding anyway\n");
1540 /* return SANE_STATUS_IO_ERROR; */
1541 }
1542 #else
1543 RIE (download_firmware_file (dev));
1544 #endif
1545
1546 RIE (gt68xx_device_get_id (dev));
1547
1548 if (!(dev->model->flags & GT68XX_FLAG_NO_STOP))
1549 RIE (gt68xx_device_stop_scan (dev));
1550
1551 RIE (gt68xx_device_get_power_status (dev, &power_ok));
1552 if (power_ok)
1553 {
1554 DBG (5, "sane_open: power ok\n");
1555 }
1556 else
1557 {
1558 DBG (0, "sane_open: power control failure: check power plug!\n");
1559 return SANE_STATUS_IO_ERROR;
1560 }
1561
1562 RIE (gt68xx_scanner_new (dev, &s));
1563 RIE (gt68xx_device_lamp_control (s->dev, SANE_TRUE, SANE_FALSE));
1564 gettimeofday (&s->lamp_on_time, 0);
1565
1566 /* insert newly opened handle into list of open handles: */
1567 s->next = first_handle;
1568 first_handle = s;
1569 *handle = s;
1570 s->scanning = SANE_FALSE;
1571 s->first_scan = SANE_TRUE;
1572 s->gamma_table = 0;
1573 s->calibrated = SANE_FALSE;
1574 RIE (init_options (s));
1575 dev->gray_mode_color = 0x02;
1576
1577 /* try to restore calibration from file */
1578 if((s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
1579 {
1580 /* error restoring calibration is non blocking */
1581 gt68xx_read_calibration(s);
1582 }
1583
1584 DBG (5, "sane_open: exit\n");
1585
1586 return SANE_STATUS_GOOD;
1587 }
1588
1589 void
sane_close(SANE_Handle handle)1590 sane_close (SANE_Handle handle)
1591 {
1592 GT68xx_Scanner *prev, *s;
1593 GT68xx_Device *dev;
1594
1595 DBG (5, "sane_close: start\n");
1596
1597 /* remove handle from list of open handles: */
1598 prev = 0;
1599 for (s = first_handle; s; s = s->next)
1600 {
1601 if (s == handle)
1602 break;
1603 prev = s;
1604 }
1605 if (!s)
1606 {
1607 DBG (5, "close: invalid handle %p\n", handle);
1608 return; /* oops, not a handle we know about */
1609 }
1610
1611 if (prev)
1612 prev->next = s->next;
1613 else
1614 first_handle = s->next;
1615
1616 if (s->val[OPT_LAMP_OFF_AT_EXIT].w == SANE_TRUE)
1617 gt68xx_device_lamp_control (s->dev, SANE_FALSE, SANE_FALSE);
1618
1619 dev = s->dev;
1620
1621 free (s->val[OPT_MODE].s);
1622 free (s->val[OPT_GRAY_MODE_COLOR].s);
1623 free (s->val[OPT_SOURCE].s);
1624 free (dev->file_name);
1625 free ((void *)(size_t)s->opt[OPT_RESOLUTION].constraint.word_list);
1626
1627 gt68xx_scanner_free (s);
1628
1629 gt68xx_device_fix_descriptor (dev);
1630
1631 gt68xx_device_deactivate (dev);
1632 gt68xx_device_close (dev);
1633
1634 DBG (5, "sane_close: exit\n");
1635 }
1636
1637 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1638 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1639 {
1640 GT68xx_Scanner *s = handle;
1641
1642 if ((unsigned) option >= NUM_OPTIONS)
1643 return 0;
1644 DBG (5, "sane_get_option_descriptor: option = %s (%d)\n",
1645 s->opt[option].name, option);
1646 return s->opt + option;
1647 }
1648
1649 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)1650 sane_control_option (SANE_Handle handle, SANE_Int option,
1651 SANE_Action action, void *val, SANE_Int * info)
1652 {
1653 GT68xx_Scanner *s = handle;
1654 SANE_Status status = SANE_STATUS_GOOD;
1655 SANE_Word cap;
1656 SANE_Int myinfo = 0;
1657
1658 DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n",
1659 (action == SANE_ACTION_GET_VALUE) ? "get" :
1660 (action == SANE_ACTION_SET_VALUE) ? "set" :
1661 (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown",
1662 s->opt[option].name, option);
1663
1664 if (info)
1665 *info = 0;
1666
1667 if (s->scanning)
1668 {
1669 DBG (1, "sane_control_option: don't call this function while "
1670 "scanning (option = %s (%d))\n", s->opt[option].name, option);
1671
1672 return SANE_STATUS_DEVICE_BUSY;
1673 }
1674 if (option >= NUM_OPTIONS || option < 0)
1675 {
1676 DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n",
1677 option);
1678 return SANE_STATUS_INVAL;
1679 }
1680
1681 cap = s->opt[option].cap;
1682
1683 if (!SANE_OPTION_IS_ACTIVE (cap))
1684 {
1685 DBG (2, "sane_control_option: option %d is inactive\n", option);
1686 return SANE_STATUS_INVAL;
1687 }
1688
1689 if (action == SANE_ACTION_GET_VALUE)
1690 {
1691 switch (option)
1692 {
1693 /* word options: */
1694 case OPT_NUM_OPTS:
1695 case OPT_RESOLUTION:
1696 case OPT_BIT_DEPTH:
1697 case OPT_FULL_SCAN:
1698 case OPT_COARSE_CAL:
1699 case OPT_COARSE_CAL_ONCE:
1700 case OPT_QUALITY_CAL:
1701 case OPT_BACKTRACK:
1702 case OPT_BACKTRACK_LINES:
1703 case OPT_PREVIEW:
1704 case OPT_LAMP_OFF_AT_EXIT:
1705 case OPT_AUTO_WARMUP:
1706 case OPT_GAMMA_VALUE:
1707 case OPT_THRESHOLD:
1708 case OPT_TL_X:
1709 case OPT_TL_Y:
1710 case OPT_BR_X:
1711 case OPT_BR_Y:
1712 *(SANE_Word *) val = s->val[option].w;
1713 break;
1714 /* string options: */
1715 case OPT_MODE:
1716 case OPT_GRAY_MODE_COLOR:
1717 case OPT_SOURCE:
1718 strcpy (val, s->val[option].s);
1719 break;
1720 case OPT_NEED_CALIBRATION_SW:
1721 *(SANE_Bool *) val = !s->calibrated;
1722 break;
1723 case OPT_PAGE_LOADED_SW:
1724 s->dev->model->command_set->document_present (s->dev, val);
1725 break;
1726 default:
1727 DBG (2, "sane_control_option: can't get unknown option %d\n",
1728 option);
1729 }
1730 }
1731 else if (action == SANE_ACTION_SET_VALUE)
1732 {
1733 if (!SANE_OPTION_IS_SETTABLE (cap))
1734 {
1735 DBG (2, "sane_control_option: option %d is not settable\n", option);
1736 return SANE_STATUS_INVAL;
1737 }
1738
1739 status = sanei_constrain_value (s->opt + option, val, &myinfo);
1740
1741 if (status != SANE_STATUS_GOOD)
1742 {
1743 DBG (2, "sane_control_option: sanei_constrain_value returned %s\n",
1744 sane_strstatus (status));
1745 return status;
1746 }
1747
1748 switch (option)
1749 {
1750 case OPT_RESOLUTION:
1751 case OPT_BIT_DEPTH:
1752 case OPT_FULL_SCAN:
1753 case OPT_PREVIEW:
1754 case OPT_TL_X:
1755 case OPT_TL_Y:
1756 case OPT_BR_X:
1757 case OPT_BR_Y:
1758 s->val[option].w = *(SANE_Word *) val;
1759 RIE (calc_parameters (s));
1760 myinfo |= SANE_INFO_RELOAD_PARAMS;
1761 break;
1762 case OPT_LAMP_OFF_AT_EXIT:
1763 case OPT_AUTO_WARMUP:
1764 case OPT_COARSE_CAL_ONCE:
1765 case OPT_BACKTRACK_LINES:
1766 case OPT_QUALITY_CAL:
1767 case OPT_GAMMA_VALUE:
1768 case OPT_THRESHOLD:
1769 s->val[option].w = *(SANE_Word *) val;
1770 break;
1771 case OPT_GRAY_MODE_COLOR:
1772 if (strcmp (s->val[option].s, val) != 0)
1773 { /* something changed */
1774 if (s->val[option].s)
1775 free (s->val[option].s);
1776 s->val[option].s = strdup (val);
1777 }
1778 break;
1779 case OPT_SOURCE:
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 if (strcmp (s->val[option].s, "Transparency Adapter") == 0)
1786 {
1787 RIE (gt68xx_device_lamp_control
1788 (s->dev, SANE_FALSE, SANE_TRUE));
1789 x_range.max = s->dev->model->x_size_ta;
1790 y_range.max = s->dev->model->y_size_ta;
1791 }
1792 else
1793 {
1794 RIE (gt68xx_device_lamp_control
1795 (s->dev, SANE_TRUE, SANE_FALSE));
1796 x_range.max = s->dev->model->x_size;
1797 y_range.max = s->dev->model->y_size;
1798 }
1799 s->first_scan = SANE_TRUE;
1800 myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1801 gettimeofday (&s->lamp_on_time, 0);
1802 }
1803 break;
1804 case OPT_MODE:
1805 if (s->val[option].s)
1806 free (s->val[option].s);
1807 s->val[option].s = strdup (val);
1808 if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
1809 {
1810 ENABLE (OPT_THRESHOLD);
1811 DISABLE (OPT_BIT_DEPTH);
1812 ENABLE (OPT_GRAY_MODE_COLOR);
1813 }
1814 else
1815 {
1816 DISABLE (OPT_THRESHOLD);
1817 if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0)
1818 {
1819 RIE (create_bpp_list (s, s->dev->model->bpp_gray_values));
1820 ENABLE (OPT_GRAY_MODE_COLOR);
1821 }
1822 else
1823 {
1824 RIE (create_bpp_list (s, s->dev->model->bpp_color_values));
1825 DISABLE (OPT_GRAY_MODE_COLOR);
1826 }
1827 if (s->bpp_list[0] < 2)
1828 DISABLE (OPT_BIT_DEPTH);
1829 else
1830 ENABLE (OPT_BIT_DEPTH);
1831 }
1832 RIE (calc_parameters (s));
1833 myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
1834 break;
1835
1836 case OPT_COARSE_CAL:
1837 s->val[option].w = *(SANE_Word *) val;
1838 if (s->val[option].w == SANE_TRUE)
1839 {
1840 ENABLE (OPT_COARSE_CAL_ONCE);
1841 s->first_scan = SANE_TRUE;
1842 }
1843 else
1844 {
1845 DISABLE (OPT_COARSE_CAL_ONCE);
1846 }
1847 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1848 break;
1849
1850 case OPT_BACKTRACK:
1851 s->val[option].w = *(SANE_Word *) val;
1852 if (s->val[option].w == SANE_TRUE)
1853 ENABLE (OPT_BACKTRACK_LINES);
1854 else
1855 DISABLE (OPT_BACKTRACK_LINES);
1856 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1857 break;
1858
1859 case OPT_CALIBRATE:
1860 status = gt68xx_sheetfed_scanner_calibrate (s);
1861 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1862 break;
1863
1864 case OPT_CLEAR_CALIBRATION:
1865 gt68xx_clear_calibration (s);
1866 myinfo |= SANE_INFO_RELOAD_OPTIONS;
1867 break;
1868
1869 default:
1870 DBG (2, "sane_control_option: can't set unknown option %d\n",
1871 option);
1872 }
1873 }
1874 else
1875 {
1876 DBG (2, "sane_control_option: unknown action %d for option %d\n",
1877 action, option);
1878 return SANE_STATUS_INVAL;
1879 }
1880 if (info)
1881 *info = myinfo;
1882
1883 DBG (5, "sane_control_option: exit\n");
1884 return status;
1885 }
1886
1887 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1888 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1889 {
1890 GT68xx_Scanner *s = handle;
1891 SANE_Status status;
1892
1893 DBG (5, "sane_get_parameters: start\n");
1894
1895 RIE (calc_parameters (s));
1896 if (params)
1897 *params = s->params;
1898
1899 DBG (4, "sane_get_parameters: format=%d, last_frame=%d, lines=%d\n",
1900 s->params.format, s->params.last_frame, s->params.lines);
1901 DBG (4, "sane_get_parameters: pixels_per_line=%d, bytes per line=%d\n",
1902 s->params.pixels_per_line, s->params.bytes_per_line);
1903 DBG (3, "sane_get_parameters: pixels %dx%dx%d\n",
1904 s->params.pixels_per_line, s->params.lines, 1 << s->params.depth);
1905
1906 DBG (5, "sane_get_parameters: exit\n");
1907
1908 return SANE_STATUS_GOOD;
1909 }
1910
1911 SANE_Status
sane_start(SANE_Handle handle)1912 sane_start (SANE_Handle handle)
1913 {
1914 GT68xx_Scanner *s = handle;
1915 GT68xx_Scan_Request scan_request;
1916 GT68xx_Scan_Parameters scan_params;
1917 SANE_Status status;
1918 SANE_Int i, gamma_size;
1919 unsigned int *buffer_pointers[3];
1920 SANE_Bool document;
1921
1922 DBG (5, "sane_start: start\n");
1923
1924 /* First make sure we have a current parameter set. Some of the
1925 parameters will be overwritten below, but that's OK. */
1926 RIE (calc_parameters (s));
1927
1928 if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w)
1929 {
1930 DBG (0, "sane_start: top left x >= bottom right x --- exiting\n");
1931 return SANE_STATUS_INVAL;
1932 }
1933 if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w)
1934 {
1935 DBG (0, "sane_start: top left y >= bottom right y --- exiting\n");
1936 return SANE_STATUS_INVAL;
1937 }
1938
1939 if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_BLUE) == 0)
1940 s->dev->gray_mode_color = 0x01;
1941 else if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_GREEN) == 0)
1942 s->dev->gray_mode_color = 0x02;
1943 else
1944 s->dev->gray_mode_color = 0x03;
1945
1946 setup_scan_request (s, &scan_request);
1947 if (!s->first_scan && s->val[OPT_COARSE_CAL_ONCE].w == SANE_TRUE)
1948 s->auto_afe = SANE_FALSE;
1949 else
1950 s->auto_afe = s->val[OPT_COARSE_CAL].w;
1951
1952 s->dev->gamma_value = s->val[OPT_GAMMA_VALUE].w;
1953 gamma_size = s->params.depth == 16 ? 65536 : 256;
1954 s->gamma_table = malloc (sizeof (SANE_Int) * gamma_size);
1955 if (!s->gamma_table)
1956 {
1957 DBG (1, "sane_start: couldn't malloc %d bytes for gamma table\n",
1958 gamma_size);
1959 return SANE_STATUS_NO_MEM;
1960 }
1961 for (i = 0; i < gamma_size; i++)
1962 {
1963 s->gamma_table[i] =
1964 (gamma_size - 1) * pow (((double) i + 1) / (gamma_size),
1965 1.0 / SANE_UNFIX (s->dev->gamma_value)) + 0.5;
1966 if (s->gamma_table[i] > (gamma_size - 1))
1967 s->gamma_table[i] = (gamma_size - 1);
1968 if (s->gamma_table[i] < 0)
1969 s->gamma_table[i] = 0;
1970 #if 0
1971 printf ("%d %d\n", i, s->gamma_table[i]);
1972 #endif
1973 }
1974
1975 if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
1976 {
1977 s->calib = s->val[OPT_QUALITY_CAL].w;
1978 }
1979
1980 if (!(s->dev->model->flags & GT68XX_FLAG_NO_STOP))
1981 RIE (gt68xx_device_stop_scan (s->dev));
1982
1983 if (!(s->dev->model->flags & GT68XX_FLAG_SHEET_FED))
1984 RIE (gt68xx_device_carriage_home (s->dev));
1985
1986 gt68xx_scanner_wait_for_positioning (s);
1987 gettimeofday (&s->start_time, 0);
1988
1989 if (s->val[OPT_BACKTRACK].w == SANE_TRUE)
1990 scan_request.backtrack = SANE_TRUE;
1991 else
1992 {
1993 if (s->val[OPT_RESOLUTION].w >= s->dev->model->ydpi_no_backtrack)
1994 scan_request.backtrack = SANE_FALSE;
1995 else
1996 scan_request.backtrack = SANE_TRUE;
1997 }
1998
1999 if (scan_request.backtrack)
2000 scan_request.backtrack_lines = s->val[OPT_BACKTRACK_LINES].w;
2001 else
2002 scan_request.backtrack_lines = 0;
2003
2004 /* don't call calibration for scanners that use sheetfed_calibrate */
2005 if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))
2006 {
2007 RIE (gt68xx_scanner_calibrate (s, &scan_request));
2008 }
2009 else
2010 {
2011 s->calib = s->calibrated;
2012 }
2013
2014 /* is possible, wait for document to be inserted before scanning */
2015 /* wait for 5 secondes max */
2016 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED
2017 && s->dev->model->command_set->document_present)
2018 {
2019 i=0;
2020 do
2021 {
2022 RIE(s->dev->model->command_set->document_present(s->dev,&document));
2023 if(document==SANE_FALSE)
2024 {
2025 i++;
2026 sleep(1);
2027 }
2028 } while ((i<5) && (document==SANE_FALSE));
2029 if(document==SANE_FALSE)
2030 {
2031 DBG (4, "sane_start: no document detected after %d s\n",i);
2032 return SANE_STATUS_NO_DOCS;
2033 }
2034 }
2035
2036 /* some sheetfed scanners need a special operation to move
2037 * paper before starting real scan */
2038 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
2039 {
2040 RIE (gt68xx_sheetfed_move_to_scan_area (s, &scan_request));
2041 }
2042
2043 /* restore calibration */
2044 if( (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)
2045 &&(s->calibrated == SANE_TRUE))
2046 {
2047 /* compute scan parameters */
2048 scan_request.calculate = SANE_TRUE;
2049 gt68xx_device_setup_scan (s->dev, &scan_request, SA_SCAN, &scan_params);
2050
2051 /* restore settings from calibration stored */
2052 memcpy(s->dev->afe,&(s->afe_params), sizeof(GT68xx_AFE_Parameters));
2053 RIE (gt68xx_assign_calibration (s, scan_params));
2054 scan_request.calculate = SANE_FALSE;
2055 }
2056
2057 /* send scan request to the scanner */
2058 RIE (gt68xx_scanner_start_scan (s, &scan_request, &scan_params));
2059
2060 for (i = 0; i < scan_params.overscan_lines; ++i)
2061 RIE (gt68xx_scanner_read_line (s, buffer_pointers));
2062 DBG (4, "sane_start: wanted: dpi=%d, x=%.1f, y=%.1f, width=%.1f, "
2063 "height=%.1f, color=%s\n", scan_request.xdpi,
2064 SANE_UNFIX (scan_request.x0),
2065 SANE_UNFIX (scan_request.y0), SANE_UNFIX (scan_request.xs),
2066 SANE_UNFIX (scan_request.ys), scan_request.color ? "color" : "gray");
2067
2068 s->line = 0;
2069 s->byte_count = s->reader->params.pixel_xs;
2070 s->total_bytes = 0;
2071 s->first_scan = SANE_FALSE;
2072
2073 #ifdef DEBUG_BRIGHTNESS
2074 s->average_white = 0;
2075 s->max_white = 0;
2076 s->min_black = 255;
2077 #endif
2078
2079 s->scanning = SANE_TRUE;
2080
2081 DBG (5, "sane_start: exit\n");
2082 return SANE_STATUS_GOOD;
2083 }
2084
2085 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)2086 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
2087 SANE_Int * len)
2088 {
2089 GT68xx_Scanner *s = handle;
2090 SANE_Status status;
2091 static unsigned int *buffer_pointers[3];
2092 SANE_Int inflate_x;
2093 SANE_Bool lineart;
2094 SANE_Int i, color, colors;
2095
2096 if (!s)
2097 {
2098 DBG (1, "sane_read: handle is null!\n");
2099 return SANE_STATUS_INVAL;
2100 }
2101
2102 if (!buf)
2103 {
2104 DBG (1, "sane_read: buf is null!\n");
2105 return SANE_STATUS_INVAL;
2106 }
2107
2108 if (!len)
2109 {
2110 DBG (1, "sane_read: len is null!\n");
2111 return SANE_STATUS_INVAL;
2112 }
2113
2114 *len = 0;
2115
2116 if (!s->scanning)
2117 {
2118 DBG (3, "sane_read: scan was cancelled, is over or has not been "
2119 "initiated yet\n");
2120 return SANE_STATUS_CANCELLED;
2121 }
2122
2123 DBG (5, "sane_read: start (line %d of %d, byte_count %d of %d)\n",
2124 s->line, s->reader->params.pixel_ys, s->byte_count,
2125 s->reader->params.pixel_xs);
2126
2127 if (s->line >= s->reader->params.pixel_ys
2128 && s->byte_count >= s->reader->params.pixel_xs)
2129 {
2130 DBG (4, "sane_read: nothing more to scan: EOF\n");
2131 gt68xx_scanner_stop_scan(s);
2132 return SANE_STATUS_EOF;
2133 }
2134
2135 inflate_x = s->val[OPT_RESOLUTION].w / s->dev->model->optical_xdpi;
2136 if (inflate_x > 1)
2137 DBG (5, "sane_read: inflating x by factor %d\n", inflate_x);
2138 else
2139 inflate_x = 1;
2140
2141 lineart = (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0)
2142 ? SANE_TRUE : SANE_FALSE;
2143
2144 if (s->reader->params.color)
2145 colors = 3;
2146 else
2147 colors = 1;
2148
2149 while ((*len) < max_len)
2150 {
2151 if (s->byte_count >= s->reader->params.pixel_xs)
2152 {
2153 if (s->line >= s->reader->params.pixel_ys)
2154 {
2155 DBG (4, "sane_read: scan complete: %d bytes, %d total\n",
2156 *len, s->total_bytes);
2157 return SANE_STATUS_GOOD;
2158 }
2159 DBG (5, "sane_read: getting line %d of %d\n", s->line,
2160 s->reader->params.pixel_ys);
2161 RIE (gt68xx_scanner_read_line (s, buffer_pointers));
2162 s->line++;
2163 s->byte_count = 0;
2164
2165 /* Apply gamma */
2166 for (color = 0; color < colors; color++)
2167 for (i = 0; i < s->reader->pixels_per_line; i++)
2168 {
2169 if (s->reader->params.depth > 8)
2170 buffer_pointers[color][i] =
2171 s->gamma_table[buffer_pointers[color][i]];
2172 else
2173 buffer_pointers[color][i] =
2174 (s->gamma_table[buffer_pointers[color][i] >> 8] << 8) +
2175 (s->gamma_table[buffer_pointers[color][i] >> 8]);
2176 }
2177 /* mirror lines */
2178 if (s->dev->model->flags & GT68XX_FLAG_MIRROR_X)
2179 {
2180 unsigned int swap;
2181
2182 for (color = 0; color < colors; color++)
2183 {
2184 for (i = 0; i < s->reader->pixels_per_line / 2; i++)
2185 {
2186 swap = buffer_pointers[color][i];
2187 buffer_pointers[color][i] =
2188 buffer_pointers[color][s->reader->pixels_per_line -
2189 1 - i];
2190 buffer_pointers[color][s->reader->pixels_per_line - 1 -
2191 i] = swap;
2192 }
2193 }
2194 }
2195 }
2196 if (lineart)
2197 {
2198 SANE_Int bit;
2199 SANE_Byte threshold = s->val[OPT_THRESHOLD].w;
2200
2201 buf[*len] = 0;
2202 for (bit = 7; bit >= 0; bit--)
2203 {
2204 SANE_Byte is_black =
2205 (((buffer_pointers[0][s->byte_count] >> 8) & 0xff) >
2206 threshold) ? 0 : 1;
2207 buf[*len] |= (is_black << bit);
2208 if ((7 - bit) % inflate_x == (inflate_x - 1))
2209 s->byte_count++;
2210 }
2211 }
2212 else if (s->reader->params.color)
2213 {
2214 /* color */
2215 if (s->reader->params.depth > 8)
2216 {
2217 SANE_Int color = (s->total_bytes / 2) % 3;
2218 if ((s->total_bytes % 2) == 0)
2219 {
2220 if (little_endian)
2221 buf[*len] = buffer_pointers[color][s->byte_count] & 0xff;
2222 else
2223 buf[*len] =
2224 (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2225 }
2226 else
2227 {
2228 if (little_endian)
2229 buf[*len] =
2230 (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2231 else
2232 buf[*len] = buffer_pointers[color][s->byte_count] & 0xff;
2233
2234 if (s->total_bytes % (inflate_x * 6) == (inflate_x * 6 - 1))
2235 s->byte_count++;
2236 }
2237 }
2238 else
2239 {
2240 SANE_Int color = s->total_bytes % 3;
2241 buf[*len] = (buffer_pointers[color][s->byte_count] >> 8) & 0xff;
2242 if (s->total_bytes % (inflate_x * 3) == (inflate_x * 3 - 1))
2243 s->byte_count++;
2244 #ifdef DEBUG_BRIGHTNESS
2245 s->average_white += buf[*len];
2246 s->max_white =
2247 (buf[*len] > s->max_white) ? buf[*len] : s->max_white;
2248 s->min_black =
2249 (buf[*len] < s->min_black) ? buf[*len] : s->min_black;
2250 #endif
2251 }
2252 }
2253 else
2254 {
2255 /* gray */
2256 if (s->reader->params.depth > 8)
2257 {
2258 if ((s->total_bytes % 2) == 0)
2259 {
2260 if (little_endian)
2261 buf[*len] = buffer_pointers[0][s->byte_count] & 0xff;
2262 else
2263 buf[*len] =
2264 (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2265 }
2266 else
2267 {
2268 if (little_endian)
2269 buf[*len] =
2270 (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2271 else
2272 buf[*len] = buffer_pointers[0][s->byte_count] & 0xff;
2273 if (s->total_bytes % (2 * inflate_x) == (2 * inflate_x - 1))
2274 s->byte_count++;
2275 }
2276 }
2277 else
2278 {
2279 buf[*len] = (buffer_pointers[0][s->byte_count] >> 8) & 0xff;
2280 if (s->total_bytes % inflate_x == (inflate_x - 1))
2281 s->byte_count++;
2282 }
2283 }
2284 (*len)++;
2285 s->total_bytes++;
2286 }
2287
2288 DBG (4, "sane_read: exit (line %d of %d, byte_count %d of %d, %d bytes, "
2289 "%d total)\n",
2290 s->line, s->reader->params.pixel_ys, s->byte_count,
2291 s->reader->params.pixel_xs, *len, s->total_bytes);
2292 return SANE_STATUS_GOOD;
2293 }
2294
2295 void
sane_cancel(SANE_Handle handle)2296 sane_cancel (SANE_Handle handle)
2297 {
2298 GT68xx_Scanner *s = handle;
2299
2300 DBG (5, "sane_cancel: start\n");
2301
2302 if (s->scanning)
2303 {
2304 s->scanning = SANE_FALSE;
2305 if (s->total_bytes != (s->params.bytes_per_line * s->params.lines))
2306 DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d "
2307 "bytes\n", s->total_bytes,
2308 s->params.bytes_per_line * s->params.lines);
2309 else
2310 {
2311 struct timeval now;
2312 int secs;
2313
2314 gettimeofday (&now, 0);
2315 secs = now.tv_sec - s->start_time.tv_sec;
2316
2317 DBG (3,
2318 "sane_cancel: scan finished, scanned %d bytes in %d seconds\n",
2319 s->total_bytes, secs);
2320 #ifdef DEBUG_BRIGHTNESS
2321 DBG (1,
2322 "sane_cancel: average white: %d, max_white=%d, min_black=%d\n",
2323 s->average_white / s->total_bytes, s->max_white, s->min_black);
2324 #endif
2325
2326 }
2327 /* some scanners don't like this command when cancelling a scan */
2328 sanei_usb_set_timeout (SHORT_TIMEOUT);
2329 gt68xx_device_fix_descriptor (s->dev);
2330 gt68xx_scanner_stop_scan (s);
2331 sanei_usb_set_timeout (LONG_TIMEOUT);
2332
2333 if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED)
2334 {
2335 gt68xx_device_paperfeed (s->dev);
2336 }
2337 else
2338 {
2339 sanei_usb_set_timeout (SHORT_TIMEOUT);
2340 gt68xx_scanner_wait_for_positioning (s);
2341 sanei_usb_set_timeout (LONG_TIMEOUT);
2342 gt68xx_device_carriage_home (s->dev);
2343 }
2344 if (s->gamma_table)
2345 {
2346 free (s->gamma_table);
2347 s->gamma_table = 0;
2348 }
2349 }
2350 else
2351 {
2352 DBG (4, "sane_cancel: scan has not been initiated yet, "
2353 "or it is already aborted\n");
2354 }
2355
2356 DBG (5, "sane_cancel: exit\n");
2357 return;
2358 }
2359
2360 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)2361 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
2362 {
2363 GT68xx_Scanner *s = handle;
2364
2365 DBG (5, "sane_set_io_mode: handle = %p, non_blocking = %s\n",
2366 handle, non_blocking == SANE_TRUE ? "true" : "false");
2367
2368 if (!s->scanning)
2369 {
2370 DBG (1, "sane_set_io_mode: not scanning\n");
2371 return SANE_STATUS_INVAL;
2372 }
2373 if (non_blocking)
2374 return SANE_STATUS_UNSUPPORTED;
2375 return SANE_STATUS_GOOD;
2376 }
2377
2378 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)2379 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
2380 {
2381 GT68xx_Scanner *s = handle;
2382
2383 DBG (5, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd);
2384
2385 if (!s->scanning)
2386 {
2387 DBG (1, "sane_get_select_fd: not scanning\n");
2388 return SANE_STATUS_INVAL;
2389 }
2390 return SANE_STATUS_UNSUPPORTED;
2391 }
2392
2393 /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
2394