1 /* sane - Scanner Access Now Easy.
2
3 This file (C) 1997 Ingo Schneider
4
5 This file is part of the SANE package.
6
7 SANE is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
11
12 SANE is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with sane; see the file COPYING.
19 If not, see <https://www.gnu.org/licenses/>.
20
21 This file implements a SANE backend for Siemens 9036 flatbed scanners. */
22
23 #include "../include/sane/config.h"
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <sys/types.h>
29
30 #ifndef PATH_MAX
31 # define PATH_MAX 1024
32 #endif
33
34 #include "../include/sane/sane.h"
35 #include "../include/sane/sanei.h"
36 #include "../include/sane/sanei_config.h"
37 #include "../include/sane/saneopts.h"
38 #include "../include/sane/sanei_scsi.h"
39 #include "s9036.h"
40
41 #define BACKEND_NAME s9036
42 #include "../include/sane/sanei_backend.h"
43
44
45 #undef Byte
46 #define Byte SANE_Byte
47
48 static const SANE_Device **devlist = NULL;
49 static int num_devices;
50 static S9036_Device *s9036_devices;
51
52
53 /* sets loc_s bytes long value at offset loc in scsi command to value size */
54 static void
set_size(Byte * loc,int loc_s,size_t size)55 set_size (Byte * loc, int loc_s, size_t size)
56 {
57 int i;
58
59 for (i = 0; i < loc_s; i++)
60 {
61 loc[loc_s - i - 1] = (size >> (i * 8)) & 0xff;
62 }
63 }
64
65 static long
reserve_unit(int fd)66 reserve_unit (int fd)
67 {
68 const Byte scsi_reserve[] =
69 {
70 0x16, 0x00, 0x00, 0x00, 0x00, 0x00
71 };
72 DBG (3, "reserve_unit()\n");
73 return sanei_scsi_cmd (fd, scsi_reserve, sizeof (scsi_reserve), 0, 0);
74 }
75
76 static long
release_unit(int fd)77 release_unit (int fd)
78 {
79 const Byte scsi_release[] =
80 {
81 0x17, 0x00, 0x00, 0x00, 0x00, 0x00
82 };
83 DBG (3, "release_unit()\n");
84 return sanei_scsi_cmd (fd, scsi_release, sizeof (scsi_release), 0, 0);
85 }
86
87 static SANE_Status
test_ready(int fd)88 test_ready (int fd)
89 {
90 static const Byte scsi_test_ready[] =
91 {
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
93 };
94
95 SANE_Status status;
96 int try;
97
98 for (try = 0; try < 1000; ++try)
99 {
100 DBG (3, "test_ready: sending TEST_UNIT_READY\n");
101 status = sanei_scsi_cmd (fd, scsi_test_ready, sizeof (scsi_test_ready),
102 0, 0);
103
104 switch (status)
105 {
106 case SANE_STATUS_DEVICE_BUSY:
107 usleep (100000); /* retry after 100ms */
108 break;
109
110 case SANE_STATUS_GOOD:
111 return status;
112
113 default:
114 DBG (1, "test_ready: test unit ready failed (%s)\n",
115 sane_strstatus (status));
116 return status;
117 }
118 }
119
120 DBG (1, "test_ready: timed out after %d attempts\n", try);
121 return SANE_STATUS_IO_ERROR;
122 }
123
124 static SANE_Status
sense_handler(int scsi_fd,u_char * result,void * arg)125 sense_handler (int scsi_fd, u_char *result, void *arg)
126 {
127 scsi_fd = scsi_fd;
128 arg = arg; /* silence compilation warnings */
129
130 if (result[0])
131 {
132 DBG (0, "sense_handler() : sense code = %02x\n", result[0]);
133 return SANE_STATUS_IO_ERROR;
134 }
135 else
136 {
137 return SANE_STATUS_GOOD;
138 }
139 }
140
141 static SANE_Status
stop_scan(int fd)142 stop_scan (int fd)
143 {
144 fd = fd; /* silence compilation warnings */
145
146 /* XXX don't know how to stop the scanner. To be tested ! */
147 #if 0
148 const Byte scsi_rewind[] =
149 {
150 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
151 };
152 DBG (1, "Trying to stop scanner...\n");
153 return sanei_scsi_cmd (fd, scsi_rewind, sizeof (scsi_rewind), 0, 0);
154 #else
155 return SANE_STATUS_GOOD;
156 #endif
157 }
158
159
160 static SANE_Status
start_scan(int fd,SANE_Bool cont)161 start_scan (int fd, SANE_Bool cont)
162 {
163 struct
164 {
165 /* Command */
166 Byte cmd;
167 Byte lun;
168 Byte res[2];
169 Byte tr_len;
170 Byte ctrl;
171
172 /* Data */
173 Byte wid;
174 }
175 scsi_start_scan;
176
177 memset (&scsi_start_scan, 0, sizeof (scsi_start_scan));
178 scsi_start_scan.cmd = 0x1b;
179 scsi_start_scan.tr_len = 1;
180 scsi_start_scan.wid = 0;
181 scsi_start_scan.ctrl = (cont == SANE_TRUE) ? 0x80 : 0x00;
182
183 DBG (1, "Starting scanner ...\n");
184 return sanei_scsi_cmd (fd, &scsi_start_scan, sizeof (scsi_start_scan), 0, 0);
185 }
186
187 static void
wait_ready(int fd)188 wait_ready (int fd)
189 {
190 # define WAIT_READY_READ_SIZE 4
191 const Byte scsi_read[] =
192 {
193 0x28, 0x00, /* opcode, lun */
194 0x80, /* data type 80 == read time left */
195 0x00, 0x00, 0x00, /* reserved */
196 0x00, 0x00, WAIT_READY_READ_SIZE, /* transfer length */
197 0x00, /* control byte */
198 };
199
200 Byte result[WAIT_READY_READ_SIZE];
201 size_t size = WAIT_READY_READ_SIZE;
202 SANE_Status status;
203
204 while (1)
205 {
206 status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read),
207 result, &size);
208
209 if (status != SANE_STATUS_GOOD || size != WAIT_READY_READ_SIZE)
210 {
211 /*
212 Command failed, the assembler code of the windows scan library
213 ignores this condition, and so do I
214 */
215 break;
216 }
217 else
218 {
219 /* left is the amount of seconds left till the scanner is
220 ready * 100 */
221 int left = result[2] * 256 + result[3];
222
223 DBG (1, "wait_ready() : %d left...\n", left);
224
225 if (!left)
226 break;
227 /* We delay only for half the given time */
228 else if (left < 200)
229 usleep (left * 5000);
230 else
231 sleep (left / 200);
232 }
233 }
234
235 return;
236 }
237
238 static SANE_Status
get_read_sizes(int fd,int * lines_available,int * bpl,int * total_lines)239 get_read_sizes (int fd, int *lines_available, int *bpl, int *total_lines)
240 {
241 # define GET_READ_SIZES_READ_SIZE 24
242
243 const Byte scsi_read[] =
244 {
245 0x28, 0x00, /* opcode, lun */
246 0x81, /* data type 81 == read time left */
247 0x00, 0x00, 0x00, /* reserved */
248 0x00, 0x00, GET_READ_SIZES_READ_SIZE, /* transfer length */
249 0x00, /* control byte */
250 };
251
252 Byte result[GET_READ_SIZES_READ_SIZE];
253 size_t size = GET_READ_SIZES_READ_SIZE;
254 SANE_Status status;
255
256 status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), result, &size);
257
258 if (status != SANE_STATUS_GOOD || size != GET_READ_SIZES_READ_SIZE)
259 {
260 /* Command failed */
261 return SANE_STATUS_IO_ERROR;
262 }
263 else
264 {
265 *lines_available = result[14] * 256 + result[15];
266 *bpl = result[12] * 256 + result[13];
267 if (total_lines)
268 *total_lines = result[10] * 256 + result[11];
269 }
270
271 DBG (1, "get_read_sizes() : %d of %d, %d\n",
272 *lines_available, total_lines ? *total_lines : -1, *bpl);
273
274 return SANE_STATUS_GOOD;
275 }
276
277 static SANE_Status
set_window(S9036_Scanner * s)278 set_window (S9036_Scanner * s)
279 /* This function sets and sends the window for scanning */
280 {
281 double pixels_per_mm = (double) s->val[OPT_RESOLUTION] / MM_PER_INCH;
282
283 SANE_Bool auto_bright = !(s->opt[OPT_BRIGHT_ADJUST].cap & SANE_CAP_INACTIVE);
284 SANE_Bool auto_contr = !(s->opt[OPT_CONTR_ADJUST].cap & SANE_CAP_INACTIVE);
285
286 /* ranges down 255 (dark) down to 1(bright) */
287 int brightness = auto_bright ? 0 : (SANE_UNFIX (s->val[OPT_BRIGHTNESS])
288 * -1.27 + 128.5);
289 /* ranges from 1 (little contrast) up to 255 (much contrast) */
290 int contrast = auto_contr ? 0 : (SANE_UNFIX (s->val[OPT_CONTRAST])
291 * 1.27 + 128.5);
292
293 /* ranges from 40 (dark) down to 0 (bright) */
294 int bright_adjust = auto_bright ? 20 - s->val[OPT_BRIGHT_ADJUST] : 0;
295 /* ranges from 20 (little contrast) down to -20 = 235 (much contrast) */
296 int contr_adjust = auto_contr ? (256 - s->val[OPT_CONTR_ADJUST]) % 256 : 0;
297
298 /* Warning ! The following structure SEEMS to be an valid SCSI-2
299 SET_WINDOW command. But e.g. the limits for the window are only
300 2 Bytes instead of 4. The scanner was built at about 1990, so
301 SCSI-2 wasn't available for development...
302 */
303
304 struct
305 {
306 Byte cmd;
307 Byte lun;
308 Byte re1[4];
309 Byte tr_len[3];
310 Byte ctrl;
311
312 Byte re2[6];
313 Byte wd_len[2];
314
315 struct
316 {
317 Byte wid;
318 Byte autobit;
319 Byte x_axis_res[2];
320 Byte y_axis_res[2];
321
322 Byte x_axis_ul[2];
323 Byte y_axis_ul[2];
324
325 Byte wwidth[2];
326 Byte wlength[2];
327
328 Byte contrast;
329 Byte threshold;
330 Byte brightness;
331
332 Byte image_comp;
333 Byte bpp;
334
335 Byte ht_pattern;
336 Byte rif_padding;
337 Byte three;
338
339 Byte null1[2];
340 Byte null2[8];
341
342 Byte null_eins;
343 Byte eins_null;
344
345 Byte contr_adjust;
346 Byte bright_adjust;
347
348 Byte null3;
349
350 }
351 wd;
352
353 }
354 cmd;
355
356 DBG (3,
357 "Setting parameters: bpp %d, res %d, bri %d, con %d, bad %d, cad %d\n",
358 s->val[OPT_DEPTH], s->val[OPT_RESOLUTION],
359 brightness, contrast, bright_adjust, contr_adjust);
360
361 memset (&cmd, 0, sizeof (cmd));
362
363 /* Commands and sizes. Original comment in German: Kommando und Groessen. */
364 cmd.cmd = 0x24;
365 set_size (cmd.tr_len, 3, 37 + 8);
366 set_size (cmd.wd_len, 2, 37);
367
368 /* Resolution. Original comment in German: Aufloesung */
369 set_size (cmd.wd.x_axis_res, 2, s->val[OPT_RESOLUTION]);
370 set_size (cmd.wd.y_axis_res, 2, s->val[OPT_RESOLUTION]);
371
372 /* Scan window position/size. Original comment in German:
373 Fensterposition / Groesse */
374 set_size (cmd.wd.x_axis_ul, 2,
375 SANE_UNFIX (s->val[OPT_TL_X]) * pixels_per_mm + 0.5);
376 set_size (cmd.wd.y_axis_ul, 2,
377 SANE_UNFIX (s->val[OPT_TL_Y]) * pixels_per_mm + 0.5);
378 set_size (cmd.wd.wwidth, 2, SANE_UNFIX (s->val[OPT_BR_X] - s->val[OPT_TL_X])
379 * pixels_per_mm + 0.5);
380 set_size (cmd.wd.wlength, 2, SANE_UNFIX (s->val[OPT_BR_Y] - s->val[OPT_TL_Y])
381 * pixels_per_mm + 0.5);
382
383 cmd.wd.contrast = contrast;
384 cmd.wd.threshold = 0x00;
385 cmd.wd.brightness = brightness;
386
387 cmd.wd.image_comp = (s->val[OPT_DEPTH] == 1) ? 0 : 2;
388 cmd.wd.bpp = s->val[OPT_DEPTH];
389
390 cmd.wd.ht_pattern = 0;
391 cmd.wd.rif_padding = 0x00;
392 cmd.wd.three = 3;
393
394 cmd.wd.null_eins = (s->val[OPT_DEPTH] == 1) ? 0 : 1;
395 cmd.wd.eins_null = (s->val[OPT_DEPTH] == 1) ? 1 : 0;
396
397 cmd.wd.contr_adjust = contr_adjust;
398 cmd.wd.bright_adjust = bright_adjust;
399
400 return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0);
401 }
402
403 /* Tell scanner to scan more data. Original comment in German:
404 Fordert Scanner auf, weiter zu scannen... */
405 static SANE_Status
request_more_data(S9036_Scanner * s)406 request_more_data (S9036_Scanner * s)
407 {
408 SANE_Status status;
409 int lines_available;
410 int bytes_per_line;
411
412 status = start_scan (s->fd, SANE_TRUE);
413 if (status != SANE_STATUS_GOOD)
414 return status;
415
416 wait_ready (s->fd);
417
418 status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, 0);
419
420 if (!lines_available || bytes_per_line != s->params.bytes_per_line)
421 {
422 return SANE_STATUS_INVAL;
423 }
424
425 if (s->lines_read + lines_available > s->params.lines)
426 return SANE_STATUS_INVAL;
427
428 s->lines_in_scanner = lines_available;
429
430 return SANE_STATUS_GOOD;
431 }
432
433 /* May only be called when there is at least one row of data to
434 be read.
435
436 Original comment in German: Darf nur aufgerufen werden, wenn
437 wirklich noch Zeilen zu scannen/lesen sind ! */
438 static SANE_Status
read_more_data(S9036_Scanner * s)439 read_more_data (S9036_Scanner * s)
440 {
441
442 static Byte cmd[] =
443 {
444 0x28, 0x00, /* opcode, lun */
445 0x00, /* data type 80 == read time left */
446 0x00, 0x00, 0x00, /* reserved */
447 0x00, 0x00, 0x00, /* transfer length */
448 0x00, /* control byte */
449 };
450
451 SANE_Status status;
452 size_t size;
453 int lines_read;
454 int bpl = s->params.bytes_per_line;
455 unsigned int i;
456
457 if (s->lines_in_scanner == 0)
458 {
459 /* No lines in scanner ? scan some more */
460 status = request_more_data (s);
461
462 if (status != SANE_STATUS_GOOD)
463 return status;
464
465 }
466
467 /* We try this 3 times */
468 while (1)
469 {
470
471 /* Request as much lines as would fit into the buffer ... */
472 lines_read = s->bufsize / bpl;
473
474 /* buffer is too small for one line: we can't handle this */
475 if (!lines_read)
476 return SANE_STATUS_INVAL;
477
478 /* We only request as many lines as there are already scanned */
479 if (lines_read > s->lines_in_scanner)
480 lines_read = s->lines_in_scanner;
481
482 set_size (&cmd[6], 3, lines_read);
483 size = lines_read * s->params.bytes_per_line;
484
485 DBG (1, "Requesting %d lines, in scanner: %d, total: %d\n", lines_read,
486 s->lines_in_scanner, s->params.lines);
487
488 status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), s->buffer, &size);
489
490 if (status != SANE_STATUS_GOOD)
491 {
492 if (s->bufsize > 4096)
493 {
494 DBG (1, "sanei_scsi_cmd(): using 4k buffer\n");
495 s->bufsize = 4096;
496 continue;
497 }
498
499 DBG (1, "sanei_scsi_cmd() = %d\n", status);
500 return SANE_STATUS_IO_ERROR;
501 }
502
503 if (size != (unsigned int) lines_read * s->params.bytes_per_line)
504 {
505 DBG (1, "sanei_scsi_cmd(): got %lu bytes, expected %d\n",
506 (u_long) size, lines_read * s->params.bytes_per_line);
507 return SANE_STATUS_INVAL;
508 }
509
510 DBG (1, "Got %lu bytes\n", (u_long) size);
511 break;
512 }
513
514
515 /* Reverse: */
516 if (s->params.depth != 1)
517 for (i = 0; i < size; i++)
518 s->buffer[i] = (255 - s->buffer[i]);
519
520 s->in_buffer += size;
521 s->lines_in_scanner -= lines_read;
522 s->lines_read += lines_read;
523
524 return SANE_STATUS_GOOD;
525 }
526
527
528 static SANE_Status
attach(const char * devname,S9036_Device ** devp)529 attach (const char *devname, S9036_Device ** devp)
530 {
531 #define ATTACH_SCSI_INQ_LEN 55
532 const Byte scsi_inquiry[] =
533 {
534 0x12, 0x00, 0x00, 0x00, ATTACH_SCSI_INQ_LEN, 0x00
535 };
536 Byte result[ATTACH_SCSI_INQ_LEN];
537
538 int fd;
539 S9036_Device *dev;
540 SANE_Status status;
541 size_t size;
542 int i;
543
544 for (dev = s9036_devices; dev; dev = dev->next)
545 if (strcmp (dev->sane.name, devname) == 0)
546 {
547 if (devp)
548 *devp = dev;
549 return SANE_STATUS_GOOD;
550 }
551
552 DBG (3, "attach: opening %s\n", devname);
553 status = sanei_scsi_open (devname, &fd, sense_handler, 0);
554 if (status != SANE_STATUS_GOOD)
555 {
556 DBG (1, "attach: open failed (%s)\n", sane_strstatus (status));
557 return SANE_STATUS_INVAL;
558 }
559
560 DBG (3, "attach: sending INQUIRY\n");
561 size = sizeof (result);
562 status = sanei_scsi_cmd (fd, scsi_inquiry, sizeof (scsi_inquiry),
563 result, &size);
564 if (status != SANE_STATUS_GOOD || size != ATTACH_SCSI_INQ_LEN)
565 {
566 DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status));
567 sanei_scsi_close (fd);
568 return status;
569 }
570
571 status = test_ready (fd);
572 sanei_scsi_close (fd);
573 if (status != SANE_STATUS_GOOD)
574 return status;
575
576 /* The structure send by the scanner after inquiry is not SCSI-2
577 compatible. The standard manufacturer/model fields are no ASCII
578 strings, but ? At offset 36 my SIEMENS scanner identifies as an
579 AGFA one ?! */
580
581 if (result[0] != 6 || strncmp ((char *)result + 36, "AGFA03", 6))
582 {
583 DBG (1, "attach: device doesn't look like a Siemens 9036 scanner\n");
584 return SANE_STATUS_INVAL;
585 }
586
587 DBG (3, "Inquiry data:\n");
588 for (i = 5; i < 55; i += 10)
589 DBG (3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
590 result[i], result[i + 1], result[i + 2], result[i + 3], result[i + 4],
591 result[i + 5], result[i + 6], result[i + 7], result[i + 8],
592 result[i + 9]);
593
594 dev = malloc (sizeof (*dev));
595
596 if (!dev)
597 return SANE_STATUS_NO_MEM;
598
599 memset (dev, 0, sizeof (*dev));
600
601 dev->sane.name = strdup (devname);
602 dev->sane.vendor = "Siemens";
603 dev->sane.model = "9036";
604 dev->sane.type = "flatbed scanner";
605
606 dev->handle = 0;
607
608 DBG (3, "attach: found S9036 scanner model\n");
609
610 ++num_devices;
611 dev->next = s9036_devices;
612 s9036_devices = dev;
613
614 if (devp)
615 *devp = dev;
616
617 return SANE_STATUS_GOOD;
618 }
619
620 static SANE_Status
do_cancel(S9036_Scanner * s)621 do_cancel (S9036_Scanner * s)
622 {
623 s->scanning = SANE_FALSE;
624
625 if (s->fd >= 0)
626 {
627 stop_scan (s->fd);
628 release_unit (s->fd);
629 sanei_scsi_close (s->fd);
630 s->fd = -1;
631 }
632
633 if (s->buffer)
634 {
635 free (s->buffer);
636 s->buffer = 0;
637 }
638
639 return SANE_STATUS_CANCELLED;
640 }
641
642
643 static SANE_Status
init_options(S9036_Scanner * s)644 init_options (S9036_Scanner * s)
645 {
646 int i;
647
648 /* Hardware Limitations: must be static ! */
649 static const SANE_Int depth_list[] =
650 {2, 1, 8};
651
652 static const SANE_Int dpi_list[] =
653 {8, 100, 200, 300, 400, 500, 600, 700, 800};
654
655 static const SANE_Range percentage_range =
656 {
657 SANE_FIX(-100), /* minimum */
658 SANE_FIX(100), /* maximum */
659 SANE_FIX(1) /* quantization */
660 };
661
662 static const SANE_Range automatic_adjust_range =
663 {-20, 20, 1};
664
665 static const SANE_Range x_range =
666 {0, SANE_FIX (8.27 * MM_PER_INCH), 0};
667 static const SANE_Range y_range =
668 {0, SANE_FIX (12.72 * MM_PER_INCH), 0};
669
670 /* ------ */
671
672 memset (s->opt, 0, sizeof (s->opt));
673 memset (s->val, 0, sizeof (s->val));
674
675 for (i = 0; i < NUM_OPTIONS; ++i)
676 {
677 s->opt[i].size = sizeof (SANE_Word);
678 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
679 }
680
681 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
682 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
683 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
684 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
685 s->val[OPT_NUM_OPTS] = NUM_OPTIONS;
686
687 /* "Mode" group: */
688
689 s->opt[OPT_MODE_GROUP].title = "Scan Mode";
690 s->opt[OPT_MODE_GROUP].desc = "";
691 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
692 s->opt[OPT_MODE_GROUP].cap = 0;
693 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
694
695 /* depth */
696 s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH;
697 s->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
698 s->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
699 s->opt[OPT_DEPTH].type = SANE_TYPE_INT;
700 s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT;
701 s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
702 s->opt[OPT_DEPTH].constraint.word_list = depth_list;
703 s->val[OPT_DEPTH] = 1;
704
705 /* resolution */
706 s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
707 s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
708 s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
709 s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
710 s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
711 s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
712 s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list;
713 s->val[OPT_RESOLUTION] = 100;
714
715 /* "Geometry" group: */
716 s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
717 s->opt[OPT_GEOMETRY_GROUP].desc = "";
718 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
719 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
720 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
721
722 /* top-left x */
723 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
724 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
725 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
726 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
727 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
728 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
729 s->opt[OPT_TL_X].constraint.range = &x_range;
730 s->val[OPT_TL_X] = 0;
731
732 /* top-left y */
733 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
734 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
735 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
736 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
737 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
738 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
739 s->opt[OPT_TL_Y].constraint.range = &y_range;
740 s->val[OPT_TL_Y] = 0;
741
742 /* bottom-right x */
743 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
744 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
745 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
746 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
747 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
748 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
749 s->opt[OPT_BR_X].constraint.range = &x_range;
750 s->val[OPT_BR_X] = x_range.max;
751
752 /* bottom-right y */
753 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
754 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
755 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
756 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
757 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
758 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
759 s->opt[OPT_BR_Y].constraint.range = &y_range;
760 s->val[OPT_BR_Y] = y_range.max;
761
762 /* "Enhancement" group: */
763 s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
764 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
765 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
766 s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
767 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
768
769 /* brightness */
770 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
771 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
772 s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
773 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
774 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_AUTOMATIC;
775 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
776 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
777 s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range;
778 s->val[OPT_BRIGHTNESS] = 0;
779
780 /* contrast */
781 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
782 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
783 s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
784 s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED;
785 s->opt[OPT_CONTRAST].cap |= SANE_CAP_AUTOMATIC;
786 s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
787 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
788 s->opt[OPT_CONTRAST].constraint.range = &percentage_range;
789 s->val[OPT_CONTRAST] = 0;
790
791 /* brightness automatic correct */
792 s->opt[OPT_BRIGHT_ADJUST].name = "adjust-bright";
793 s->opt[OPT_BRIGHT_ADJUST].title = "Automatic brightness adjust";
794 s->opt[OPT_BRIGHT_ADJUST].desc = "Controls the automatic brightness of the "
795 "acquired image. This option is active for automatic brightness only.";
796 s->opt[OPT_BRIGHT_ADJUST].type = SANE_TYPE_INT;
797 s->opt[OPT_BRIGHT_ADJUST].cap |= SANE_CAP_INACTIVE;
798 s->opt[OPT_BRIGHT_ADJUST].unit = SANE_UNIT_NONE;
799 s->opt[OPT_BRIGHT_ADJUST].constraint_type = SANE_CONSTRAINT_RANGE;
800 s->opt[OPT_BRIGHT_ADJUST].constraint.range = &automatic_adjust_range;
801 s->val[OPT_BRIGHT_ADJUST] = 0;
802
803 /* contrast automatic correct */
804 s->opt[OPT_CONTR_ADJUST].name = "adjust-contr";
805 s->opt[OPT_CONTR_ADJUST].title = "Automatic contrast adjust";
806 s->opt[OPT_CONTR_ADJUST].desc = "Controls the automatic contrast of the "
807 " acquired image. This option is active for automatic contrast only.";
808 s->opt[OPT_CONTR_ADJUST].type = SANE_TYPE_INT;
809 s->opt[OPT_CONTR_ADJUST].cap |= SANE_CAP_INACTIVE;
810 s->opt[OPT_CONTR_ADJUST].unit = SANE_UNIT_NONE;
811 s->opt[OPT_CONTR_ADJUST].constraint_type = SANE_CONSTRAINT_RANGE;
812 s->opt[OPT_CONTR_ADJUST].constraint.range = &automatic_adjust_range;
813 s->val[OPT_CONTR_ADJUST] = 0;
814
815 return SANE_STATUS_GOOD;
816 }
817
818 static SANE_Status
attach_one(const char * dev)819 attach_one (const char *dev)
820 {
821 attach (dev, 0);
822 return SANE_STATUS_GOOD;
823 }
824
825 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)826 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
827 {
828 char dev_name[PATH_MAX];
829 size_t len;
830 FILE *fp;
831
832 authorize = authorize; /* silence compilation warnings */
833
834 DBG_INIT ();
835
836 if (version_code)
837 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0);
838
839 fp = sanei_config_open ("s9036.conf");
840 if (!fp)
841 {
842 /* default to /dev/scanner instead of insisting on config file */
843 attach ("/dev/scanner", 0);
844 return SANE_STATUS_GOOD;
845 }
846
847 while (sanei_config_read (dev_name, sizeof (dev_name), fp))
848 {
849 if (dev_name[0] == '#') /* ignore line comments */
850 continue;
851 len = strlen (dev_name);
852
853 if (!len)
854 continue; /* ignore empty lines */
855
856 sanei_config_attach_matching_devices (dev_name, attach_one);
857 }
858 fclose (fp);
859 return SANE_STATUS_GOOD;
860 }
861
862 void
sane_exit(void)863 sane_exit (void)
864 {
865 S9036_Device *dev, *next;
866
867 for (dev = s9036_devices; dev; dev = next)
868 {
869 next = dev->next;
870 if (dev->handle)
871 sane_close (dev->handle);
872 free (dev);
873 }
874
875 if (devlist)
876 free (devlist);
877 }
878
879 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)880 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
881 {
882 S9036_Device *dev;
883 int i;
884
885 local_only = local_only; /* silence compilation warnings */
886
887 if (devlist)
888 free (devlist);
889
890 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
891 if (!devlist)
892 return SANE_STATUS_NO_MEM;
893
894 for (dev = s9036_devices, i = 0; i < num_devices; dev = dev->next)
895 devlist[i++] = &dev->sane;
896 devlist[i++] = 0;
897
898 *device_list = devlist;
899 return SANE_STATUS_GOOD;
900 }
901
902 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)903 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
904 {
905 S9036_Device *dev;
906 SANE_Status status;
907 S9036_Scanner *s;
908
909 if (devicename[0])
910 {
911 status = attach (devicename, &dev);
912 if (status != SANE_STATUS_GOOD)
913 return status;
914 }
915 else
916 {
917 /* empty devicname -> use first device */
918 dev = s9036_devices;
919 }
920
921 if (!dev)
922 return SANE_STATUS_INVAL;
923
924 if (dev->handle)
925 return SANE_STATUS_DEVICE_BUSY;
926
927 s = malloc (sizeof (*s));
928 if (!s)
929 return SANE_STATUS_NO_MEM;
930
931 memset (s, 0, sizeof (*s));
932 s->scanning = SANE_FALSE;
933 s->fd = -1;
934 s->hw = dev;
935 s->hw->handle = s;
936
937 init_options (s);
938
939 *handle = s;
940 return SANE_STATUS_GOOD;
941 }
942
943 void
sane_close(SANE_Handle handle)944 sane_close (SANE_Handle handle)
945 {
946 S9036_Scanner *s = handle;
947
948 if (s->scanning)
949 do_cancel (handle);
950
951 s->hw->handle = 0;
952
953 free (handle);
954 }
955
956 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)957 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
958 {
959 S9036_Scanner *s = handle;
960
961 if ((unsigned) option >= NUM_OPTIONS)
962 return 0;
963 return s->opt + option;
964 }
965
966 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)967 sane_control_option (SANE_Handle handle, SANE_Int option,
968 SANE_Action action, void *val, SANE_Int * info)
969 {
970 S9036_Scanner *s = handle;
971 SANE_Status status;
972
973 if (info)
974 *info = 0;
975
976 if (s->scanning)
977 return SANE_STATUS_DEVICE_BUSY;
978
979 if (option >= NUM_OPTIONS || !SANE_OPTION_IS_ACTIVE (s->opt[option].cap))
980 return SANE_STATUS_UNSUPPORTED;
981
982 if (action == SANE_ACTION_GET_VALUE)
983 {
984
985 switch (option)
986 {
987 case OPT_DEPTH:
988 case OPT_RESOLUTION:
989 case OPT_TL_X:
990 case OPT_TL_Y:
991 case OPT_BR_X:
992 case OPT_BR_Y:
993 case OPT_NUM_OPTS:
994 case OPT_BRIGHTNESS:
995 case OPT_CONTRAST:
996 case OPT_BRIGHT_ADJUST:
997 case OPT_CONTR_ADJUST:
998 *(SANE_Word *) val = s->val[option];
999 break;
1000 default:
1001 return SANE_STATUS_UNSUPPORTED;
1002 }
1003
1004 }
1005 else if (action == SANE_ACTION_SET_VALUE)
1006 {
1007
1008 if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap))
1009 return SANE_STATUS_UNSUPPORTED;
1010
1011 status = sanei_constrain_value (s->opt + option, val, info);
1012 if (status != SANE_STATUS_GOOD)
1013 return status;
1014
1015 switch (option)
1016 {
1017 case OPT_DEPTH:
1018 case OPT_RESOLUTION:
1019 case OPT_TL_X:
1020 case OPT_TL_Y:
1021 case OPT_BR_X:
1022 case OPT_BR_Y:
1023 if (info)
1024 *info |= SANE_INFO_RELOAD_PARAMS;
1025 // fall through
1026 case OPT_BRIGHT_ADJUST:
1027 case OPT_CONTR_ADJUST:
1028 s->val[option] = *(SANE_Word *) val;
1029 break;
1030 case OPT_BRIGHTNESS:
1031 if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_BRIGHT_ADJUST].cap))
1032 {
1033 s->opt[OPT_BRIGHT_ADJUST].cap |= SANE_CAP_INACTIVE;
1034 if (info)
1035 *info |= SANE_INFO_RELOAD_OPTIONS;
1036 }
1037 s->val[option] = *(SANE_Word *) val;
1038 break;
1039 case OPT_CONTRAST:
1040 if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_CONTR_ADJUST].cap))
1041 {
1042 s->opt[OPT_CONTR_ADJUST].cap |= SANE_CAP_INACTIVE;
1043 if (info)
1044 *info |= SANE_INFO_RELOAD_OPTIONS;
1045 }
1046 s->val[option] = *(SANE_Word *) val;
1047 break;
1048 default:
1049 return SANE_STATUS_UNSUPPORTED;
1050 }
1051
1052 }
1053 else if (action == SANE_ACTION_SET_AUTO)
1054 {
1055
1056 if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap))
1057 return SANE_STATUS_UNSUPPORTED;
1058
1059 switch (option)
1060 {
1061 case OPT_BRIGHTNESS:
1062 if (!SANE_OPTION_IS_ACTIVE (s->opt[OPT_BRIGHT_ADJUST].cap))
1063 {
1064 s->opt[OPT_BRIGHT_ADJUST].cap &= ~SANE_CAP_INACTIVE;
1065 if (info)
1066 *info |= SANE_INFO_RELOAD_OPTIONS;
1067 }
1068 break;
1069 case OPT_CONTRAST:
1070 if (!SANE_OPTION_IS_ACTIVE (s->opt[OPT_CONTR_ADJUST].cap))
1071 {
1072 s->opt[OPT_CONTR_ADJUST].cap &= ~SANE_CAP_INACTIVE;
1073 if (info)
1074 *info |= SANE_INFO_RELOAD_OPTIONS;
1075 }
1076 break;
1077 default:
1078 return SANE_STATUS_UNSUPPORTED;
1079 }
1080
1081 }
1082 else
1083 return SANE_STATUS_UNSUPPORTED;
1084 return SANE_STATUS_GOOD;
1085 }
1086
1087 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1088 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1089 {
1090 S9036_Scanner *s = handle;
1091
1092 if (!s->scanning)
1093 {
1094 double width, height, dpi;
1095
1096 memset (&s->params, 0, sizeof (s->params));
1097
1098 s->params.format = SANE_FRAME_GRAY;
1099 s->params.last_frame = SANE_TRUE;
1100
1101 s->params.depth = s->val[OPT_DEPTH];
1102
1103 width = SANE_UNFIX (s->val[OPT_BR_X] - s->val[OPT_TL_X]);
1104 height = SANE_UNFIX (s->val[OPT_BR_Y] - s->val[OPT_TL_Y]);
1105 dpi = s->val[OPT_RESOLUTION];
1106
1107 /* make best-effort guess at what parameters will look like once
1108 scanning starts. */
1109 if (dpi > 0.0 && width > 0.0 && height > 0.0)
1110 {
1111 double dots_per_mm = dpi / MM_PER_INCH;
1112
1113 s->params.pixels_per_line = width * dots_per_mm + 0.5;
1114 s->params.lines = height * dots_per_mm + 0.5;
1115 }
1116
1117 s->params.bytes_per_line =
1118 (s->params.pixels_per_line + (8 - s->params.depth))
1119 / (8 / s->params.depth);
1120 }
1121
1122 if (params)
1123 *params = s->params;
1124 return SANE_STATUS_GOOD;
1125 }
1126
1127 SANE_Status
sane_start(SANE_Handle handle)1128 sane_start (SANE_Handle handle)
1129 {
1130 S9036_Scanner *s = handle;
1131 SANE_Status status;
1132
1133 if (s->scanning)
1134 do_cancel (s);
1135
1136 /* First make sure we have a current parameter set. Some of the
1137 parameters will be overwritten below, but that's OK. */
1138 status = sane_get_parameters (s, 0);
1139 if (status != SANE_STATUS_GOOD)
1140 return status;
1141
1142 if (s->fd < 0)
1143 {
1144 status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0);
1145 if (status != SANE_STATUS_GOOD)
1146 {
1147 DBG (1, "open: open of %s failed: %s\n",
1148 s->hw->sane.name, sane_strstatus (status));
1149 s->fd = -1;
1150 return status;
1151 }
1152 }
1153
1154 status = test_ready (s->fd);
1155 if (status != SANE_STATUS_GOOD)
1156 {
1157 DBG (1, "open: test_ready() failed: %s\n", sane_strstatus (status));
1158 sanei_scsi_close (s->fd);
1159 s->fd = -1;
1160 return status;
1161 }
1162
1163 status = reserve_unit (s->fd);
1164 if (status != SANE_STATUS_GOOD)
1165 {
1166 DBG (1, "open: reserve_unit() failed: %s\n", sane_strstatus (status));
1167 sanei_scsi_close (s->fd);
1168 s->fd = -1;
1169 return status;
1170 }
1171
1172 status = set_window (s);
1173 if (status != SANE_STATUS_GOOD)
1174 {
1175 DBG (1, "open: set_window() failed: %s\n", sane_strstatus (status));
1176 release_unit (s->fd);
1177 sanei_scsi_close (s->fd);
1178 s->fd = -1;
1179 return status;
1180 }
1181
1182 s->scanning = SANE_TRUE;
1183
1184 status = start_scan (s->fd, SANE_FALSE);
1185 if (status != SANE_STATUS_GOOD)
1186 {
1187 DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status));
1188 do_cancel (s);
1189 return status;
1190 }
1191
1192 wait_ready (s->fd);
1193
1194 {
1195 int lines_available = 0, bytes_per_line = 0, total_lines = 0;
1196
1197 status = get_read_sizes (s->fd, &lines_available, &bytes_per_line,
1198 &total_lines);
1199 if (status != SANE_STATUS_GOOD)
1200 {
1201 DBG (1, "open: get_read_sizes() failed: %s\n",
1202 sane_strstatus (status));
1203 do_cancel (s);
1204 return status;
1205 }
1206
1207 if (!lines_available || !bytes_per_line || !total_lines)
1208 {
1209 DBG (1, "open: invalid_sizes(): %d, %d, %d\n",
1210 lines_available, bytes_per_line, total_lines);
1211 do_cancel (s);
1212 return SANE_STATUS_INVAL;
1213 }
1214
1215 s->params.lines = total_lines;
1216 s->params.bytes_per_line = bytes_per_line;
1217 s->params.pixels_per_line = bytes_per_line * (8 / s->params.depth);
1218
1219 s->lines_in_scanner = lines_available;
1220 s->lines_read = 0;
1221
1222 /* Buffer must be at least 4k */
1223 s->bufsize = (sanei_scsi_max_request_size < 4096) ?
1224 4096 : sanei_scsi_max_request_size;
1225
1226 s->buffer = (Byte *) malloc (s->bufsize * sizeof (Byte));
1227
1228 if (!s->buffer)
1229 {
1230 DBG (1, "open malloc(%lu) failed.\n", (u_long) s->bufsize);
1231 do_cancel (s);
1232 return SANE_STATUS_NO_MEM;
1233 }
1234 s->bufstart = s->buffer;
1235 s->in_buffer = 0;
1236 }
1237
1238 return SANE_STATUS_GOOD;
1239 }
1240
1241 static void
copy_buffer(S9036_Scanner * s,SANE_Byte ** buf,SANE_Int * max_len,SANE_Int * len)1242 copy_buffer (S9036_Scanner * s, SANE_Byte ** buf, SANE_Int * max_len,
1243 SANE_Int * len)
1244 {
1245 if (*max_len > (SANE_Int) s->in_buffer)
1246 {
1247 memcpy (*buf, s->bufstart, s->in_buffer);
1248 *buf += s->in_buffer;
1249 *len += s->in_buffer;
1250 *max_len -= s->in_buffer;
1251
1252 s->bufstart = s->buffer;
1253 s->in_buffer = 0;
1254 }
1255 else
1256 {
1257 memcpy (*buf, s->bufstart, *max_len);
1258 s->bufstart += *max_len;
1259 s->in_buffer -= *max_len;
1260
1261 *buf += *max_len;
1262 *len += *max_len;
1263 *max_len = 0;
1264 }
1265 }
1266
1267
1268 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)1269 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
1270 SANE_Int * len)
1271 {
1272 S9036_Scanner *s = handle;
1273 SANE_Status status;
1274
1275 if (s->scanning != SANE_TRUE || max_len == 0)
1276 return SANE_STATUS_INVAL;
1277
1278 *len = 0;
1279
1280 DBG (3, "sane_read(%d) : lines_read %d\n", max_len, s->lines_read);
1281
1282 while (max_len > (SANE_Int) s->in_buffer && s->lines_read < s->params.lines)
1283 {
1284
1285 if (s->in_buffer == 0)
1286 {
1287 status = read_more_data (s);
1288
1289 if (status != SANE_STATUS_GOOD)
1290 {
1291 DBG (1, "sane_read: read_more_data() failed (%s)\n",
1292 sane_strstatus (status));
1293 do_cancel (s);
1294 return status;
1295 }
1296 }
1297
1298 copy_buffer (s, &buf, &max_len, len);
1299
1300 if (!max_len || s->lines_read >= s->params.lines)
1301 return SANE_STATUS_GOOD;
1302 }
1303
1304 /* If we reached this point, there are either enough bytes in the buffer,
1305 or, if the buffer is empty, we already reached the end of the page */
1306
1307 if (s->in_buffer > 0)
1308 {
1309 copy_buffer (s, &buf, &max_len, len);
1310 return SANE_STATUS_GOOD;
1311 }
1312 else
1313 {
1314 do_cancel (s);
1315 DBG (1, "EOF\n");
1316 return SANE_STATUS_EOF;
1317 }
1318 }
1319
1320 void
sane_cancel(SANE_Handle handle)1321 sane_cancel (SANE_Handle handle)
1322 {
1323 S9036_Scanner *s = handle;
1324 do_cancel (s);
1325 }
1326
1327 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)1328 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1329 {
1330 handle = handle; /* silence compilation warnings */
1331
1332 DBG (1, "sane_set_io_mode(%d)\n", non_blocking);
1333
1334 return (non_blocking == SANE_TRUE) ?
1335 SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD;
1336 }
1337
1338 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)1339 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1340 {
1341 handle = handle;
1342 fd = fd; /* silence compilation warnings */
1343
1344 return SANE_STATUS_UNSUPPORTED;
1345 }
1346