1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1996, 1997 Andreas Beck
3 Copyright (C) 2000, 2001 Michael Herder <crapsite@gmx.net>
4 Copyright (C) 2001, 2002 Henning Meier-Geinitz <henning@meier-geinitz.de>
5 Copyright (C) 2008 Stéphane Voltz <stef.dev@free.fr>
6 This file is part of the SANE package.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21 As a special exception, the authors of SANE give permission for
22 additional uses of the libraries contained in this release of SANE.
23
24 The exception is that, if you link a SANE library with other files
25 to produce an executable, this does not by itself cause the
26 resulting executable to be covered by the GNU General Public
27 License. Your use of that executable is in no way restricted on
28 account of linking the SANE library code into it.
29
30 This exception does not, however, invalidate any other reasons why
31 the executable file might be covered by the GNU General Public
32 License.
33
34 If you submit changes to SANE to the maintainers to be included in
35 a subsequent release, you agree by submitting the changes that
36 those changes may be distributed with this exception intact.
37
38 If you write modifications of your own for SANE, it is your choice
39 whether to permit this exception to apply to your modifications.
40 If you do not wish that, delete this exception notice. */
41
42 #define BUILD 9
43
44 #include "../include/sane/config.h"
45
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <errno.h>
52 #include <sys/time.h>
53
54 #include "../include/sane/sane.h"
55 #include "../include/sane/sanei.h"
56 #include "../include/sane/saneopts.h"
57
58 #define BACKEND_NAME pnm
59 #include "../include/sane/sanei_backend.h"
60
61 #ifndef PATH_MAX
62 # define PATH_MAX 1024
63 #endif
64
65 #define MAGIC (void *)0xab730324
66
67 static int is_open = 0;
68 static int rgb_comp = 0;
69 static int three_pass = 0;
70 static int hand_scanner = 0;
71 static int pass = 0;
72 static char filename[PATH_MAX] = "/tmp/input.ppm";
73 static SANE_Word status_none = SANE_TRUE;
74 static SANE_Word status_eof = SANE_FALSE;
75 static SANE_Word status_jammed = SANE_FALSE;
76 static SANE_Word status_nodocs = SANE_FALSE;
77 static SANE_Word status_coveropen = SANE_FALSE;
78 static SANE_Word status_ioerror = SANE_FALSE;
79 static SANE_Word status_nomem = SANE_FALSE;
80 static SANE_Word status_accessdenied = SANE_FALSE;
81 static SANE_Word test_option = 0;
82 #ifdef SANE_STATUS_WARMING_UP
83 static SANE_Word warming_up = SANE_FALSE;
84 static struct timeval start;
85 #endif
86
87 static SANE_Fixed bright = 0;
88 static SANE_Word res = 75;
89 static SANE_Fixed contr = 0;
90 static SANE_Bool gray = SANE_FALSE;
91 static SANE_Bool usegamma = SANE_FALSE;
92 static SANE_Word gamma[4][256];
93 static enum
94 {
95 ppm_bitmap,
96 ppm_greyscale,
97 ppm_color
98 }
99 ppm_type = ppm_color;
100 static FILE *infile = NULL;
101 static const SANE_Word resbit_list[] = {
102 17,
103 75, 90, 100, 120, 135, 150, 165, 180, 195,
104 200, 210, 225, 240, 255, 270, 285, 300
105 };
106 static const SANE_Range percentage_range = {
107 SANE_FIX(-100), /* minimum */
108 SANE_FIX(100), /* maximum */
109 SANE_FIX(0) /* quantization */
110 };
111 static const SANE_Range gamma_range = {
112 0, /* minimum */
113 255, /* maximum */
114 0 /* quantization */
115 };
116 typedef enum
117 {
118 opt_num_opts = 0,
119 opt_source_group,
120 opt_filename,
121 opt_resolution,
122 opt_enhancement_group,
123 opt_brightness,
124 opt_contrast,
125 opt_grayify,
126 opt_three_pass,
127 opt_hand_scanner,
128 opt_default_enhancements,
129 opt_read_only,
130 opt_gamma_group,
131 opt_custom_gamma,
132 opt_gamma,
133 opt_gamma_r,
134 opt_gamma_g,
135 opt_gamma_b,
136 opt_status_group,
137 opt_status,
138 opt_status_eof,
139 opt_status_jammed,
140 opt_status_nodocs,
141 opt_status_coveropen,
142 opt_status_ioerror,
143 opt_status_nomem,
144 opt_status_accessdenied,
145
146 /* must come last: */
147 num_options
148 }
149 pnm_opts;
150
151 static SANE_Option_Descriptor sod[] = {
152 { /* opt_num_opts */
153 SANE_NAME_NUM_OPTIONS,
154 SANE_TITLE_NUM_OPTIONS,
155 SANE_DESC_NUM_OPTIONS,
156 SANE_TYPE_INT,
157 SANE_UNIT_NONE,
158 sizeof (SANE_Word),
159 SANE_CAP_SOFT_DETECT,
160 SANE_CONSTRAINT_NONE,
161 {NULL}
162 }
163 ,
164 { /* opt_source_group */
165 "",
166 SANE_I18N ("Source Selection"),
167 "",
168 SANE_TYPE_GROUP,
169 SANE_UNIT_NONE,
170 0,
171 0,
172 SANE_CONSTRAINT_NONE,
173 {NULL}
174 }
175 ,
176 { /* opt_filename */
177 SANE_NAME_FILE,
178 SANE_TITLE_FILE,
179 SANE_DESC_FILE,
180 SANE_TYPE_STRING,
181 SANE_UNIT_NONE,
182 sizeof (filename),
183 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
184 SANE_CONSTRAINT_NONE,
185 {NULL}
186 }
187 ,
188 {
189 /* opt_resolution */
190 SANE_NAME_SCAN_RESOLUTION,
191 SANE_TITLE_SCAN_RESOLUTION,
192 SANE_DESC_SCAN_RESOLUTION,
193 SANE_TYPE_INT,
194 SANE_UNIT_DPI,
195 sizeof (SANE_Word),
196 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC,
197 SANE_CONSTRAINT_WORD_LIST,
198 {(SANE_String_Const *) resbit_list}
199 }
200 ,
201 { /* opt_enhancement_group */
202 "",
203 SANE_I18N ("Image Enhancement"),
204 "",
205 SANE_TYPE_GROUP,
206 SANE_UNIT_NONE,
207 0,
208 0,
209 SANE_CONSTRAINT_NONE,
210 {NULL}
211 }
212 ,
213 { /* opt_brightness */
214 SANE_NAME_BRIGHTNESS,
215 SANE_TITLE_BRIGHTNESS,
216 SANE_DESC_BRIGHTNESS,
217 SANE_TYPE_FIXED,
218 SANE_UNIT_PERCENT,
219 sizeof (SANE_Word),
220 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
221 SANE_CONSTRAINT_RANGE,
222 {(SANE_String_Const *) & percentage_range} /* this is ANSI conformant! */
223 }
224 ,
225 { /* opt_contrast */
226 SANE_NAME_CONTRAST,
227 SANE_TITLE_CONTRAST,
228 SANE_DESC_CONTRAST,
229 SANE_TYPE_FIXED,
230 SANE_UNIT_PERCENT,
231 sizeof (SANE_Word),
232 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
233 SANE_CONSTRAINT_RANGE,
234 {(SANE_String_Const *) & percentage_range} /* this is ANSI conformant! */
235 }
236 ,
237 { /* opt_grayify */
238 "grayify",
239 SANE_I18N ("Grayify"),
240 SANE_I18N ("Load the image as grayscale."),
241 SANE_TYPE_BOOL,
242 SANE_UNIT_NONE,
243 sizeof (SANE_Word),
244 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
245 SANE_CONSTRAINT_NONE,
246 {NULL}
247 }
248 ,
249 { /* opt_three_pass */
250 "three-pass",
251 SANE_I18N ("Three-Pass Simulation"),
252 SANE_I18N
253 ("Simulate a three-pass scanner by returning 3 separate frames. "
254 "For kicks, it returns green, then blue, then red."),
255 SANE_TYPE_BOOL,
256 SANE_UNIT_NONE,
257 sizeof (SANE_Word),
258 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
259 SANE_CONSTRAINT_NONE,
260 {NULL}
261 }
262 ,
263 { /* opt_hand_scanner */
264 "hand-scanner",
265 SANE_I18N ("Hand-Scanner Simulation"),
266 SANE_I18N ("Simulate a hand-scanner. Hand-scanners often do not know the "
267 "image height a priori. Instead, they return a height of -1. "
268 "Setting this option allows one to test whether a frontend can "
269 "handle this correctly."),
270 SANE_TYPE_BOOL,
271 SANE_UNIT_NONE,
272 sizeof (SANE_Word),
273 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
274 SANE_CONSTRAINT_NONE,
275 {NULL}
276 }
277 ,
278 { /* opt_default_enhancements */
279 "default-enhancements",
280 SANE_I18N ("Defaults"),
281 SANE_I18N ("Set default values for enhancement controls (brightness & "
282 "contrast)."),
283 SANE_TYPE_BUTTON,
284 SANE_UNIT_NONE,
285 0,
286 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
287 SANE_CONSTRAINT_NONE,
288 {NULL}
289 }
290 ,
291 { /* opt_read_only */
292 "read-only",
293 SANE_I18N ("Read only test-option"),
294 SANE_I18N ("Let's see whether frontends can treat this right"),
295 SANE_TYPE_INT,
296 SANE_UNIT_PERCENT,
297 sizeof (SANE_Word),
298 SANE_CAP_SOFT_DETECT,
299 SANE_CONSTRAINT_NONE,
300 {NULL}
301 }
302 ,
303 { /* opt_gamma_group */
304 "",
305 SANE_I18N ("Gamma Tables"),
306 "",
307 SANE_TYPE_GROUP,
308 SANE_UNIT_NONE,
309 0,
310 0,
311 SANE_CONSTRAINT_NONE,
312 {NULL}
313 }
314 ,
315 { /* opt_custom_gamma */
316 SANE_NAME_CUSTOM_GAMMA,
317 SANE_TITLE_CUSTOM_GAMMA,
318 SANE_DESC_CUSTOM_GAMMA,
319 SANE_TYPE_BOOL,
320 SANE_UNIT_NONE,
321 sizeof (SANE_Word),
322 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
323 SANE_CONSTRAINT_NONE,
324 {NULL}
325 }
326 ,
327 { /* opt_gamma */
328 SANE_NAME_GAMMA_VECTOR,
329 SANE_TITLE_GAMMA_VECTOR,
330 SANE_DESC_GAMMA_VECTOR,
331 SANE_TYPE_INT,
332 SANE_UNIT_NONE,
333 sizeof (SANE_Word) * 256,
334 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
335 SANE_CONSTRAINT_RANGE,
336 {(SANE_String_Const *) & gamma_range}
337 }
338 ,
339 { /* opt_gamma_r */
340 SANE_NAME_GAMMA_VECTOR_R,
341 SANE_TITLE_GAMMA_VECTOR_R,
342 SANE_DESC_GAMMA_VECTOR_R,
343 SANE_TYPE_INT,
344 SANE_UNIT_NONE,
345 sizeof (SANE_Word) * 256,
346 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
347 SANE_CONSTRAINT_RANGE,
348 {(SANE_String_Const *) & gamma_range}
349 }
350 ,
351 { /* opt_gamma_g */
352 SANE_NAME_GAMMA_VECTOR_G,
353 SANE_TITLE_GAMMA_VECTOR_G,
354 SANE_DESC_GAMMA_VECTOR_G,
355 SANE_TYPE_INT,
356 SANE_UNIT_NONE,
357 sizeof (SANE_Word) * 256,
358 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
359 SANE_CONSTRAINT_RANGE,
360 {(SANE_String_Const *) & gamma_range}
361 }
362 ,
363 { /* opt_gamma_b */
364 SANE_NAME_GAMMA_VECTOR_B,
365 SANE_TITLE_GAMMA_VECTOR_B,
366 SANE_DESC_GAMMA_VECTOR_B,
367 SANE_TYPE_INT,
368 SANE_UNIT_NONE,
369 sizeof (SANE_Word) * 256,
370 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE,
371 SANE_CONSTRAINT_RANGE,
372 {(SANE_String_Const *) & gamma_range}
373 }
374 ,
375 { /* opt_status_group */
376 "",
377 SANE_I18N ("Status Code Simulation"),
378 "",
379 SANE_TYPE_GROUP,
380 SANE_UNIT_NONE,
381 0,
382 SANE_CAP_ADVANCED,
383 SANE_CONSTRAINT_NONE,
384 {NULL}
385 }
386 ,
387 { /* opt_status */
388 "status",
389 SANE_I18N ("Do not force status code"),
390 SANE_I18N ("Do not force the backend to return a status code."),
391 SANE_TYPE_BOOL,
392 SANE_UNIT_NONE,
393 sizeof (SANE_Bool),
394 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
395 SANE_CONSTRAINT_NONE,
396 {NULL}
397 }
398 ,
399 { /* opt_status_eof */
400 "status-eof",
401 SANE_I18N ("Return SANE_STATUS_EOF"),
402 SANE_I18N ("Force the backend to return the status code SANE_STATUS_EOF "
403 "after sane_read() has been called."),
404 SANE_TYPE_BOOL,
405 SANE_UNIT_NONE,
406 sizeof (SANE_Bool),
407 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
408 SANE_CONSTRAINT_NONE,
409 {NULL}
410 }
411 ,
412 { /* opt_status_jammed */
413 "status-jammed",
414 SANE_I18N ("Return SANE_STATUS_JAMMED"),
415 SANE_I18N
416 ("Force the backend to return the status code SANE_STATUS_JAMMED "
417 "after sane_read() has been called."),
418 SANE_TYPE_BOOL,
419 SANE_UNIT_NONE,
420 sizeof (SANE_Bool),
421 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
422 SANE_CONSTRAINT_NONE,
423 {NULL}
424 }
425 ,
426 { /* opt_status_nodocs */
427 "status-nodocs",
428 SANE_I18N ("Return SANE_STATUS_NO_DOCS"),
429 SANE_I18N ("Force the backend to return the status code "
430 "SANE_STATUS_NO_DOCS after sane_read() has been called."),
431 SANE_TYPE_BOOL,
432 SANE_UNIT_NONE,
433 sizeof (SANE_Bool),
434 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
435 SANE_CONSTRAINT_NONE,
436 {NULL}
437 }
438 ,
439 { /* opt_status_coveropen */
440 "status-coveropen",
441 SANE_I18N ("Return SANE_STATUS_COVER_OPEN"),
442 SANE_I18N ("Force the backend to return the status code "
443 "SANE_STATUS_COVER_OPEN after sane_read() has been called."),
444 SANE_TYPE_BOOL,
445 SANE_UNIT_NONE,
446 sizeof (SANE_Bool),
447 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
448 SANE_CONSTRAINT_NONE,
449 {NULL}
450 }
451 ,
452 { /* opt_status_ioerror */
453 "status-ioerror",
454 SANE_I18N ("Return SANE_STATUS_IO_ERROR"),
455 SANE_I18N ("Force the backend to return the status code "
456 "SANE_STATUS_IO_ERROR after sane_read() has been called."),
457 SANE_TYPE_BOOL,
458 SANE_UNIT_NONE,
459 sizeof (SANE_Bool),
460 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
461 SANE_CONSTRAINT_NONE,
462 {NULL}
463 }
464 ,
465 { /* opt_status_nomem */
466 "status-nomem",
467 SANE_I18N ("Return SANE_STATUS_NO_MEM"),
468 SANE_I18N
469 ("Force the backend to return the status code SANE_STATUS_NO_MEM "
470 "after sane_read() has been called."),
471 SANE_TYPE_BOOL,
472 SANE_UNIT_NONE,
473 sizeof (SANE_Bool),
474 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
475 SANE_CONSTRAINT_NONE,
476 {NULL}
477 }
478 ,
479 { /* opt_status_accessdenied */
480 "status-accessdenied",
481 SANE_I18N ("Return SANE_STATUS_ACCESS_DENIED"),
482 SANE_I18N ("Force the backend to return the status code "
483 "SANE_STATUS_ACCESS_DENIED after sane_read() has been called."),
484 SANE_TYPE_BOOL,
485 SANE_UNIT_NONE,
486 sizeof (SANE_Bool),
487 SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT,
488 SANE_CONSTRAINT_NONE,
489 {NULL}
490 }
491 };
492
493 static SANE_Parameters parms = {
494 SANE_FRAME_RGB,
495 0,
496 0, /* Number of bytes returned per scan line: */
497 0, /* Number of pixels per scan line. */
498 0, /* Number of lines for the current scan. */
499 8, /* Number of bits per sample. */
500 };
501
502 /* This library is a demo implementation of a SANE backend. It
503 implements a virtual device, a PNM file-filter. */
504 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)505 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
506 {
507 DBG_INIT ();
508
509 DBG (2, "sane_init: version_code %s 0, authorize %s 0\n",
510 version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!=");
511 DBG (1, "sane_init: SANE pnm backend version %d.%d.%d from %s\n",
512 SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING);
513
514 if (version_code)
515 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
516 return SANE_STATUS_GOOD;
517 }
518
519 void
sane_exit(void)520 sane_exit (void)
521 {
522 DBG (2, "sane_exit\n");
523 return;
524 }
525
526 /* Device select/open/close */
527
528 static const SANE_Device dev[] = {
529 {
530 "0",
531 "Noname",
532 "PNM file reader",
533 "virtual device"},
534 {
535 "1",
536 "Noname",
537 "PNM file reader",
538 "virtual device"},
539 #ifdef SANE_STATUS_HW_LOCKED
540 {
541 "locked",
542 "Noname",
543 "Hardware locked",
544 "virtual device"},
545 #endif
546 #ifdef SANE_STATUS_WARMING_UP
547 {
548 "warmup",
549 "Noname",
550 "Always warming up",
551 "virtual device"},
552 #endif
553 };
554
555 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)556 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
557 {
558 static const SANE_Device *devlist[] = {
559 dev + 0, dev + 1,
560 #ifdef SANE_STATUS_HW_LOCKED
561 dev + 2,
562 #endif
563 #ifdef SANE_STATUS_WARMING_UP
564 dev + 3,
565 #endif
566 0
567 };
568
569 DBG (2, "sane_get_devices: local_only = %d\n", local_only);
570 *device_list = devlist;
571 return SANE_STATUS_GOOD;
572 }
573
574 SANE_Status
sane_open(SANE_String_Const devicename, SANE_Handle * handle)575 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
576 {
577 int i;
578
579 if (!devicename)
580 return SANE_STATUS_INVAL;
581 DBG (2, "sane_open: devicename = \"%s\"\n", devicename);
582
583 if (!devicename[0])
584 i = 0;
585 else
586 for (i = 0; i < NELEMS (dev); ++i)
587 if (strcmp (devicename, dev[i].name) == 0)
588 break;
589 if (i >= NELEMS (dev))
590 return SANE_STATUS_INVAL;
591
592 if (is_open)
593 return SANE_STATUS_DEVICE_BUSY;
594
595 is_open = 1;
596 *handle = MAGIC;
597 for (i = 0; i < 256; i++)
598 {
599 gamma[0][i] = i;
600 gamma[1][i] = i;
601 gamma[2][i] = i;
602 gamma[3][i] = i;
603 }
604
605 #ifdef SANE_STATUS_HW_LOCKED
606 if(strncmp(devicename,"locked",6)==0)
607 return SANE_STATUS_HW_LOCKED;
608 #endif
609
610 #ifdef SANE_STATUS_WARMING_UP
611 if(strncmp(devicename,"warmup",6)==0)
612 {
613 warming_up = SANE_TRUE;
614 start.tv_sec = 0;
615 }
616 #endif
617
618 return SANE_STATUS_GOOD;
619 }
620
621 void
sane_close(SANE_Handle handle)622 sane_close (SANE_Handle handle)
623 {
624 DBG (2, "sane_close\n");
625 if (handle == MAGIC)
626 is_open = 0;
627 }
628
629 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)630 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
631 {
632 DBG (2, "sane_get_option_descriptor: option = %d\n", option);
633 if (handle != MAGIC || !is_open)
634 return NULL; /* wrong device */
635 if (option < 0 || option >= NELEMS (sod))
636 return NULL;
637 return &sod[option];
638 }
639
640 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info)641 sane_control_option (SANE_Handle handle, SANE_Int option,
642 SANE_Action action, void *value, SANE_Int * info)
643 {
644 SANE_Int myinfo = 0;
645 SANE_Status status;
646 int v;
647 v = 75;
648
649 DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n",
650 handle, option, action, value, (void *) info);
651
652 if (handle != MAGIC || !is_open)
653 {
654 DBG (1, "sane_control_option: unknown handle or not open\n");
655 return SANE_STATUS_INVAL; /* Unknown handle ... */
656 }
657
658 if (option < 0 || option >= NELEMS (sod))
659 {
660 DBG (1, "sane_control_option: option %d < 0 or >= number of options\n",
661 option);
662 return SANE_STATUS_INVAL; /* Unknown option ... */
663 }
664
665 if (!SANE_OPTION_IS_ACTIVE (sod[option].cap))
666 {
667 DBG (4, "sane_control_option: option is inactive\n");
668 return SANE_STATUS_INVAL;
669 }
670
671 switch (action)
672 {
673 case SANE_ACTION_SET_AUTO:
674 if (!SANE_OPTION_IS_SETTABLE (sod[option].cap))
675 {
676 DBG (4, "sane_control_option: option is not settable\n");
677 return SANE_STATUS_INVAL;
678 }
679 status = sanei_constrain_value (sod + option, (void *) &v, &myinfo);
680 if (status != SANE_STATUS_GOOD)
681 return status;
682 switch (option)
683 {
684 case opt_resolution:
685 res = 75;
686 myinfo |= SANE_INFO_RELOAD_PARAMS;
687 break;
688 default:
689 return SANE_STATUS_INVAL;
690 }
691 break;
692 case SANE_ACTION_SET_VALUE:
693 if (!SANE_OPTION_IS_SETTABLE (sod[option].cap))
694 {
695 DBG (4, "sane_control_option: option is not settable\n");
696 return SANE_STATUS_INVAL;
697 }
698 status = sanei_constrain_value (sod + option, value, &myinfo);
699 if (status != SANE_STATUS_GOOD)
700 return status;
701 switch (option)
702 {
703 case opt_filename:
704 if ((strlen (value) + 1) > sizeof (filename))
705 return SANE_STATUS_NO_MEM;
706 strcpy (filename, value);
707 myinfo |= SANE_INFO_RELOAD_PARAMS;
708 break;
709 case opt_resolution:
710 res = *(SANE_Word *) value;
711 break;
712 case opt_brightness:
713 bright = *(SANE_Word *) value;
714 break;
715 case opt_contrast:
716 contr = *(SANE_Word *) value;
717 break;
718 case opt_grayify:
719 gray = !!*(SANE_Word *) value;
720 if (usegamma)
721 {
722 if (gray)
723 {
724 sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE;
725 sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
726 sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
727 sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
728 }
729 else
730 {
731 sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
732 sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE;
733 sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE;
734 sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE;
735 }
736 }
737 else
738 {
739 sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
740 sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
741 sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
742 sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
743 }
744 myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
745 break;
746 case opt_three_pass:
747 three_pass = !!*(SANE_Word *) value;
748 myinfo |= SANE_INFO_RELOAD_PARAMS;
749 break;
750 case opt_hand_scanner:
751 hand_scanner = !!*(SANE_Word *) value;
752 myinfo |= SANE_INFO_RELOAD_PARAMS;
753 break;
754 case opt_default_enhancements:
755 bright = contr = 0;
756 myinfo |= SANE_INFO_RELOAD_OPTIONS;
757 break;
758 case opt_custom_gamma:
759 usegamma = *(SANE_Word *) value;
760 /* activate/deactivate gamma */
761 if (usegamma)
762 {
763 test_option = 100;
764 if (gray)
765 {
766 sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE;
767 sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
768 sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
769 sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
770 }
771 else
772 {
773 sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
774 sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE;
775 sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE;
776 sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE;
777 }
778 }
779 else
780 {
781 test_option = 0;
782 sod[opt_gamma].cap |= SANE_CAP_INACTIVE;
783 sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE;
784 sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE;
785 sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE;
786 }
787 myinfo |= SANE_INFO_RELOAD_OPTIONS;
788 break;
789 case opt_gamma:
790 memcpy (&gamma[0][0], (SANE_Word *) value,
791 256 * sizeof (SANE_Word));
792 myinfo |= SANE_INFO_RELOAD_OPTIONS;
793 break;
794 case opt_gamma_r:
795 memcpy (&gamma[1][0], (SANE_Word *) value,
796 256 * sizeof (SANE_Word));
797 myinfo |= SANE_INFO_RELOAD_OPTIONS;
798 break;
799 case opt_gamma_g:
800 memcpy (&gamma[2][0], (SANE_Word *) value,
801 256 * sizeof (SANE_Word));
802 myinfo |= SANE_INFO_RELOAD_OPTIONS;
803 break;
804 case opt_gamma_b:
805 memcpy (&gamma[3][0], (SANE_Word *) value,
806 256 * sizeof (SANE_Word));
807 myinfo |= SANE_INFO_RELOAD_OPTIONS;
808 break;
809 /* status */
810 case opt_status:
811 status_none = *(SANE_Word *) value;
812 if (status_none)
813 {
814 status_eof = SANE_FALSE;
815 status_jammed = SANE_FALSE;
816 status_nodocs = SANE_FALSE;
817 status_coveropen = SANE_FALSE;
818 status_ioerror = SANE_FALSE;
819 status_nomem = SANE_FALSE;
820 status_accessdenied = SANE_FALSE;
821 }
822 myinfo |= SANE_INFO_RELOAD_OPTIONS;
823 break;
824 case opt_status_eof:
825 status_eof = *(SANE_Word *) value;
826 if (status_eof)
827 {
828 status_none = SANE_FALSE;
829 status_jammed = SANE_FALSE;
830 status_nodocs = SANE_FALSE;
831 status_coveropen = SANE_FALSE;
832 status_ioerror = SANE_FALSE;
833 status_nomem = SANE_FALSE;
834 status_accessdenied = SANE_FALSE;
835 }
836 myinfo |= SANE_INFO_RELOAD_OPTIONS;
837 break;
838 case opt_status_jammed:
839 status_jammed = *(SANE_Word *) value;
840 if (status_jammed)
841 {
842 status_eof = SANE_FALSE;
843 status_none = SANE_FALSE;
844 status_nodocs = SANE_FALSE;
845 status_coveropen = SANE_FALSE;
846 status_ioerror = SANE_FALSE;
847 status_nomem = SANE_FALSE;
848 status_accessdenied = SANE_FALSE;
849 }
850 myinfo |= SANE_INFO_RELOAD_OPTIONS;
851 break;
852 case opt_status_nodocs:
853 status_nodocs = *(SANE_Word *) value;
854 if (status_nodocs)
855 {
856 status_eof = SANE_FALSE;
857 status_jammed = SANE_FALSE;
858 status_none = SANE_FALSE;
859 status_coveropen = SANE_FALSE;
860 status_ioerror = SANE_FALSE;
861 status_nomem = SANE_FALSE;
862 status_accessdenied = SANE_FALSE;
863 }
864 myinfo |= SANE_INFO_RELOAD_OPTIONS;
865 break;
866 case opt_status_coveropen:
867 status_coveropen = *(SANE_Word *) value;
868 if (status_coveropen)
869 {
870 status_eof = SANE_FALSE;
871 status_jammed = SANE_FALSE;
872 status_nodocs = SANE_FALSE;
873 status_none = SANE_FALSE;
874 status_ioerror = SANE_FALSE;
875 status_nomem = SANE_FALSE;
876 status_accessdenied = SANE_FALSE;
877 }
878 myinfo |= SANE_INFO_RELOAD_OPTIONS;
879 break;
880 case opt_status_ioerror:
881 status_ioerror = *(SANE_Word *) value;
882 if (status_ioerror)
883 {
884 status_eof = SANE_FALSE;
885 status_jammed = SANE_FALSE;
886 status_nodocs = SANE_FALSE;
887 status_coveropen = SANE_FALSE;
888 status_none = SANE_FALSE;
889 status_nomem = SANE_FALSE;
890 status_accessdenied = SANE_FALSE;
891 }
892 myinfo |= SANE_INFO_RELOAD_OPTIONS;
893 break;
894 case opt_status_nomem:
895 status_nomem = *(SANE_Word *) value;
896 if (status_nomem)
897 {
898 status_eof = SANE_FALSE;
899 status_jammed = SANE_FALSE;
900 status_nodocs = SANE_FALSE;
901 status_coveropen = SANE_FALSE;
902 status_ioerror = SANE_FALSE;
903 status_none = SANE_FALSE;
904 status_accessdenied = SANE_FALSE;
905 }
906 myinfo |= SANE_INFO_RELOAD_OPTIONS;
907 break;
908 case opt_status_accessdenied:
909 status_accessdenied = *(SANE_Word *) value;
910 if (status_accessdenied)
911 {
912 status_eof = SANE_FALSE;
913 status_jammed = SANE_FALSE;
914 status_nodocs = SANE_FALSE;
915 status_coveropen = SANE_FALSE;
916 status_ioerror = SANE_FALSE;
917 status_nomem = SANE_FALSE;
918 status_none = SANE_FALSE;
919 }
920 myinfo |= SANE_INFO_RELOAD_OPTIONS;
921 break;
922 default:
923 return SANE_STATUS_INVAL;
924 }
925 break;
926 case SANE_ACTION_GET_VALUE:
927 switch (option)
928 {
929 case opt_num_opts:
930 *(SANE_Word *) value = NELEMS (sod);
931 break;
932 case opt_filename:
933 strcpy (value, filename);
934 break;
935 case opt_resolution:
936 *(SANE_Word *) value = res;
937 break;
938 case opt_brightness:
939 *(SANE_Word *) value = bright;
940 break;
941 case opt_contrast:
942 *(SANE_Word *) value = contr;
943 break;
944 case opt_grayify:
945 *(SANE_Word *) value = gray;
946 break;
947 case opt_three_pass:
948 *(SANE_Word *) value = three_pass;
949 break;
950 case opt_hand_scanner:
951 *(SANE_Word *) value = hand_scanner;
952 break;
953 case opt_read_only:
954 *(SANE_Word *) value = test_option;
955 break;
956 case opt_custom_gamma:
957 *(SANE_Word *) value = usegamma;
958 break;
959 case opt_gamma:
960 memcpy ((SANE_Word *) value, &gamma[0][0],
961 256 * sizeof (SANE_Word));
962 break;
963 case opt_gamma_r:
964 memcpy ((SANE_Word *) value, &gamma[1][0],
965 256 * sizeof (SANE_Word));
966 break;
967 case opt_gamma_g:
968 memcpy ((SANE_Word *) value, &gamma[2][0],
969 256 * sizeof (SANE_Word));
970 break;
971 case opt_gamma_b:
972 memcpy ((SANE_Word *) value, &gamma[3][0],
973 256 * sizeof (SANE_Word));
974 break;
975 case opt_status:
976 *(SANE_Word *) value = status_none;
977 break;
978 case opt_status_eof:
979 *(SANE_Word *) value = status_eof;
980 break;
981 case opt_status_jammed:
982 *(SANE_Word *) value = status_jammed;
983 break;
984 case opt_status_nodocs:
985 *(SANE_Word *) value = status_nodocs;
986 break;
987 case opt_status_coveropen:
988 *(SANE_Word *) value = status_coveropen;
989 break;
990 case opt_status_ioerror:
991 *(SANE_Word *) value = status_ioerror;
992 break;
993 case opt_status_nomem:
994 *(SANE_Word *) value = status_nomem;
995 break;
996 case opt_status_accessdenied:
997 *(SANE_Word *) value = status_accessdenied;
998 break;
999 default:
1000 return SANE_STATUS_INVAL;
1001 }
1002 break;
1003 }
1004 if (info)
1005 *info = myinfo;
1006 return SANE_STATUS_GOOD;
1007 }
1008
1009 static void
get_line(char *buf, int len, FILE * f)1010 get_line (char *buf, int len, FILE * f)
1011 {
1012 do
1013 fgets (buf, len, f);
1014 while (*buf == '#');
1015 }
1016
1017 static int
getparmfromfile(void)1018 getparmfromfile (void)
1019 {
1020 FILE *fn;
1021 int x, y;
1022 char buf[1024];
1023
1024 parms.depth = 8;
1025 parms.bytes_per_line = parms.pixels_per_line = parms.lines = 0;
1026 if ((fn = fopen (filename, "rb")) == NULL)
1027 {
1028 DBG (1, "getparmfromfile: unable to open file \"%s\"\n", filename);
1029 return -1;
1030 }
1031
1032 /* Skip comments. */
1033 do
1034 get_line (buf, sizeof (buf), fn);
1035 while (*buf == '#');
1036 if (!strncmp (buf, "P4", 2))
1037 {
1038 /* Binary monochrome. */
1039 parms.depth = 1;
1040 ppm_type = ppm_bitmap;
1041 }
1042 else if (!strncmp (buf, "P5", 2))
1043 {
1044 /* Grayscale. */
1045 parms.depth = 8;
1046 ppm_type = ppm_greyscale;
1047 }
1048 else if (!strncmp (buf, "P6", 2))
1049 {
1050 /* Color. */
1051 parms.depth = 8;
1052 ppm_type = ppm_color;
1053 }
1054 else
1055 {
1056 DBG (1, "getparmfromfile: %s is not a recognized PPM\n", filename);
1057 fclose (fn);
1058 return -1;
1059 }
1060
1061 /* Skip comments. */
1062 do
1063 get_line (buf, sizeof (buf), fn);
1064 while (*buf == '#');
1065 sscanf (buf, "%d %d", &x, &y);
1066
1067 parms.last_frame = SANE_TRUE;
1068 parms.bytes_per_line = (ppm_type == ppm_bitmap) ? (x + 7) / 8 : x;
1069 parms.pixels_per_line = x;
1070 if (hand_scanner)
1071 parms.lines = -1;
1072 else
1073 parms.lines = y;
1074 if ((ppm_type == ppm_greyscale) || (ppm_type == ppm_bitmap) || gray)
1075 parms.format = SANE_FRAME_GRAY;
1076 else
1077 {
1078 if (three_pass)
1079 {
1080 parms.format = SANE_FRAME_RED + (pass + 1) % 3;
1081 parms.last_frame = (pass >= 2);
1082 }
1083 else
1084 {
1085 parms.format = SANE_FRAME_RGB;
1086 parms.bytes_per_line *= 3;
1087 }
1088 }
1089 fclose (fn);
1090 return 0;
1091 }
1092
1093 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)1094 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1095 {
1096 int rc = SANE_STATUS_GOOD;
1097
1098 DBG (2, "sane_get_parameters\n");
1099 if (handle != MAGIC || !is_open)
1100 rc = SANE_STATUS_INVAL; /* Unknown handle ... */
1101 else if (getparmfromfile ())
1102 rc = SANE_STATUS_INVAL;
1103 *params = parms;
1104 return rc;
1105 }
1106
1107 SANE_Status
sane_start(SANE_Handle handle)1108 sane_start (SANE_Handle handle)
1109 {
1110 char buf[1024];
1111 int nlines;
1112 #ifdef SANE_STATUS_WARMING_UP
1113 struct timeval current;
1114 #endif
1115
1116 DBG (2, "sane_start\n");
1117 rgb_comp = 0;
1118 if (handle != MAGIC || !is_open)
1119 return SANE_STATUS_INVAL; /* Unknown handle ... */
1120
1121 #ifdef SANE_STATUS_WARMING_UP
1122 if(warming_up == SANE_TRUE)
1123 {
1124 gettimeofday(¤t,NULL);
1125 if(current.tv_sec-start.tv_sec>5)
1126 {
1127 start.tv_sec = current.tv_sec;
1128 return SANE_STATUS_WARMING_UP;
1129 }
1130 if(current.tv_sec-start.tv_sec<5)
1131 return SANE_STATUS_WARMING_UP;
1132 }
1133 #endif
1134
1135 if (infile != NULL)
1136 {
1137 fclose (infile);
1138 infile = NULL;
1139 if (!three_pass || ++pass >= 3)
1140 return SANE_STATUS_EOF;
1141 }
1142
1143 if (getparmfromfile ())
1144 return SANE_STATUS_INVAL;
1145
1146 if ((infile = fopen (filename, "rb")) == NULL)
1147 {
1148 DBG (1, "sane_start: unable to open file \"%s\"\n", filename);
1149 return SANE_STATUS_INVAL;
1150 }
1151
1152 /* Skip the header (only two lines for a bitmap). */
1153 nlines = (ppm_type == ppm_bitmap) ? 1 : 0;
1154 while (nlines < 3)
1155 {
1156 /* Skip comments. */
1157 get_line (buf, sizeof (buf), infile);
1158 if (*buf != '#')
1159 nlines++;
1160 }
1161
1162 return SANE_STATUS_GOOD;
1163 }
1164
1165 static SANE_Int rgblength = 0;
1166 static SANE_Byte *rgbbuf = 0;
1167 static SANE_Byte rgbleftover[3] = { 0, 0, 0 };
1168
1169 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length)1170 sane_read (SANE_Handle handle, SANE_Byte * data,
1171 SANE_Int max_length, SANE_Int * length)
1172 {
1173 int len, x, hlp;
1174
1175 DBG (2, "sane_read: max_length = %d, rgbleftover = {%d, %d, %d}\n",
1176 max_length, rgbleftover[0], rgbleftover[1], rgbleftover[2]);
1177 if (!length)
1178 {
1179 DBG (1, "sane_read: length == NULL\n");
1180 return SANE_STATUS_INVAL;
1181 }
1182 *length = 0;
1183 if (!data)
1184 {
1185 DBG (1, "sane_read: data == NULL\n");
1186 return SANE_STATUS_INVAL;
1187 }
1188 if (handle != MAGIC)
1189 {
1190 DBG (1, "sane_read: unknown handle\n");
1191 return SANE_STATUS_INVAL;
1192 }
1193 if (!is_open)
1194 {
1195 DBG (1, "sane_read: call sane_open first\n");
1196 return SANE_STATUS_INVAL;
1197 }
1198 if (!infile)
1199 {
1200 DBG (1, "sane_read: scan was cancelled\n");
1201 return SANE_STATUS_CANCELLED;
1202 }
1203 if (feof (infile))
1204 {
1205 DBG (2, "sane_read: EOF reached\n");
1206 return SANE_STATUS_EOF;
1207 }
1208
1209 if (status_jammed == SANE_TRUE)
1210 return SANE_STATUS_JAMMED;
1211 if (status_eof == SANE_TRUE)
1212 return SANE_STATUS_EOF;
1213 if (status_nodocs == SANE_TRUE)
1214 return SANE_STATUS_NO_DOCS;
1215 if (status_coveropen == SANE_TRUE)
1216 return SANE_STATUS_COVER_OPEN;
1217 if (status_ioerror == SANE_TRUE)
1218 return SANE_STATUS_IO_ERROR;
1219 if (status_nomem == SANE_TRUE)
1220 return SANE_STATUS_NO_MEM;
1221 if (status_accessdenied == SANE_TRUE)
1222 return SANE_STATUS_ACCESS_DENIED;
1223
1224 /* Allocate a buffer for the RGB values. */
1225 if (ppm_type == ppm_color && (gray || three_pass))
1226 {
1227 SANE_Byte *p, *q, *rgbend;
1228 if (rgbbuf == 0 || rgblength < 3 * max_length)
1229 {
1230 /* Allocate a new rgbbuf. */
1231 free (rgbbuf);
1232 rgblength = 3 * max_length;
1233 rgbbuf = malloc (rgblength);
1234 if (rgbbuf == 0)
1235 return SANE_STATUS_NO_MEM;
1236 }
1237 else
1238 rgblength = 3 * max_length;
1239
1240 /* Copy any leftovers into the buffer. */
1241 q = rgbbuf;
1242 p = rgbleftover + 1;
1243 while (p - rgbleftover <= rgbleftover[0])
1244 *q++ = *p++;
1245
1246 /* Slurp in the RGB buffer. */
1247 len = fread (q, 1, rgblength - rgbleftover[0], infile);
1248 rgbend = rgbbuf + len;
1249
1250 q = data;
1251 if (gray)
1252 {
1253 /* Zip through the buffer, converting color data to grayscale. */
1254 for (p = rgbbuf; p < rgbend; p += 3)
1255 *q++ = ((long) p[0] + p[1] + p[2]) / 3;
1256 }
1257 else
1258 {
1259 /* Zip through the buffer, extracting data for this pass. */
1260 for (p = (rgbbuf + (pass + 1) % 3); p < rgbend; p += 3)
1261 *q++ = *p;
1262 }
1263
1264 /* Save any leftovers in the array. */
1265 rgbleftover[0] = len % 3;
1266 p = rgbbuf + (len - rgbleftover[0]);
1267 q = rgbleftover + 1;
1268 while (p < rgbend)
1269 *q++ = *p++;
1270
1271 len /= 3;
1272 }
1273 else
1274 /* Suck in as much of the file as possible, since it's already in the
1275 correct format. */
1276 len = fread (data, 1, max_length, infile);
1277
1278 if (len == 0)
1279 {
1280 if (feof (infile))
1281 {
1282 DBG (2, "sane_read: EOF reached\n");
1283 return SANE_STATUS_EOF;
1284 }
1285 else
1286 {
1287 DBG (1, "sane_read: error while reading file (%s)\n",
1288 strerror (errno));
1289 return SANE_STATUS_IO_ERROR;
1290 }
1291 }
1292
1293 if (parms.depth == 8)
1294 {
1295 /* Do the transformations ... DEMO ONLY ! THIS MAKES NO SENSE ! */
1296 for (x = 0; x < len; x++)
1297 {
1298 hlp = *((unsigned char *) data + x) - 128;
1299 hlp *= (contr + (100 << SANE_FIXED_SCALE_SHIFT));
1300 hlp /= 100 << SANE_FIXED_SCALE_SHIFT;
1301 hlp += (bright >> SANE_FIXED_SCALE_SHIFT) + 128;
1302 if (hlp < 0)
1303 hlp = 0;
1304 if (hlp > 255)
1305 hlp = 255;
1306 *(data + x) = hlp;
1307 }
1308 /*gamma */
1309 if (usegamma)
1310 {
1311 unsigned char uc;
1312 if (gray)
1313 {
1314 for (x = 0; x < len; x++)
1315 {
1316 uc = *((unsigned char *) data + x);
1317 uc = gamma[0][uc];
1318 *(data + x) = uc;
1319 }
1320 }
1321 else
1322 {
1323 for (x = 0; x < len; x++)
1324 {
1325 if (parms.format == SANE_FRAME_RGB)
1326 {
1327 uc = *((unsigned char *) (data + x));
1328 uc = (unsigned char) gamma[rgb_comp + 1][(int) uc];
1329 *((unsigned char *) data + x) = uc;
1330 rgb_comp += 1;
1331 if (rgb_comp > 2)
1332 rgb_comp = 0;
1333 }
1334 else
1335 {
1336 int f = 0;
1337 if (parms.format == SANE_FRAME_RED)
1338 f = 1;
1339 if (parms.format == SANE_FRAME_GREEN)
1340 f = 2;
1341 if (parms.format == SANE_FRAME_BLUE)
1342 f = 3;
1343 if (f)
1344 {
1345 uc = *((unsigned char *) (data + x));
1346 uc = (unsigned char) gamma[f][(int) uc];
1347 *((unsigned char *) data + x) = uc;
1348 }
1349 }
1350 }
1351 }
1352 }
1353 }
1354 *length = len;
1355 DBG (2, "sane_read: read %d bytes\n", len);
1356 return SANE_STATUS_GOOD;
1357 }
1358
1359 void
sane_cancel(SANE_Handle handle)1360 sane_cancel (SANE_Handle handle)
1361 {
1362 DBG (2, "sane_cancel: handle = %p\n", handle);
1363 pass = 0;
1364 if (infile != NULL)
1365 {
1366 fclose (infile);
1367 infile = NULL;
1368 }
1369 return;
1370 }
1371
1372 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)1373 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1374 {
1375 DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle,
1376 non_blocking);
1377 if (!infile)
1378 {
1379 DBG (1, "sane_set_io_mode: not scanning\n");
1380 return SANE_STATUS_INVAL;
1381 }
1382 if (non_blocking)
1383 return SANE_STATUS_UNSUPPORTED;
1384 return SANE_STATUS_GOOD;
1385 }
1386
1387 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int * fd)1388 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1389 {
1390 DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle,
1391 fd ? "!=" : "=");
1392 return SANE_STATUS_UNSUPPORTED;
1393 }
1394