1 /*
2 * epson2.c - SANE library for Epson scanners.
3 *
4 * Based on Kazuhiro Sasayama previous
5 * Work on epson.[ch] file from the SANE package.
6 * Please see those files for additional copyrights.
7 *
8 * Copyright (C) 2006-10 Tower Technologies
9 * Author: Alessandro Zummo <a.zummo@towertech.it>
10 *
11 * This file is part of the SANE package.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2.
16 */
17
18 /* debugging levels:
19 *
20 * 127 e2_recv buffer
21 * 125 e2_send buffer
22 * 32 more network progression
23 * 24 network header
24 * 23 network info
25 * 20 usb cmd counters
26 * 18 sane_read
27 * 17 setvalue, getvalue, control_option
28 * 16 gamma table
29 * 15 e2_send, e2_recv calls
30 * 13 e2_cmd_info_block
31 * 12 epson_cmd_simple
32 * 11 even more
33 * 10 more debug in ESC/I commands
34 * 9 ESC x/FS x in e2_send
35 * 8 ESC/I commands
36 * 7 open/close/attach
37 * 6 print_params
38 * 5 basic functions
39 * 3 status information
40 * 1 scanner info and capabilities
41 * warnings
42 */
43
44 #include "sane/config.h"
45
46 #include "epson2.h"
47
48 #include <limits.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <stdlib.h>
52 #include <ctype.h>
53 #include <fcntl.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <sys/time.h>
57 #include <sys/types.h>
58 #ifdef HAVE_SYS_SOCKET_H
59 #include <sys/socket.h>
60 #endif
61
62 #include "sane/saneopts.h"
63 #include "sane/sanei_scsi.h"
64 #include "sane/sanei_usb.h"
65 #include "sane/sanei_pio.h"
66 #include "sane/sanei_tcp.h"
67 #include "sane/sanei_udp.h"
68 #include "sane/sanei_backend.h"
69 #include "sane/sanei_config.h"
70
71 #include "epson2-io.h"
72 #include "epson2-commands.h"
73 #include "epson2-ops.h"
74
75 #include "epson2_scsi.h"
76 #include "epson_usb.h"
77 #include "epson2_net.h"
78
79 /*
80 * Definition of the mode_param struct, that is used to
81 * specify the valid parameters for the different scan modes.
82 *
83 * The depth variable gets updated when the bit depth is modified.
84 */
85
86 struct mode_param mode_params[] = {
87 {0, 0x00, 0x30, 1},
88 {0, 0x00, 0x30, 8},
89 {1, 0x02, 0x00, 8},
90 {0, 0x00, 0x30, 1}
91 };
92
93 static SANE_String_Const mode_list[] = {
94 SANE_VALUE_SCAN_MODE_LINEART,
95 SANE_VALUE_SCAN_MODE_GRAY,
96 SANE_VALUE_SCAN_MODE_COLOR,
97 #ifdef SANE_FRAME_IR
98 SANE_I18N("Infrared"),
99 #endif
100 NULL
101 };
102
103 static const SANE_String_Const adf_mode_list[] = {
104 SANE_I18N("Simplex"),
105 SANE_I18N("Duplex"),
106 NULL
107 };
108
109 /* Define the different scan sources */
110
111 #define FBF_STR SANE_I18N("Flatbed")
112 #define TPU_STR SANE_I18N("Transparency Unit")
113 #define TPU_STR2 SANE_I18N("TPU8x10")
114 #define ADF_STR SANE_I18N("Automatic Document Feeder")
115
116 /*
117 * source list need one dummy entry (save device settings is crashing).
118 * NOTE: no const - this list gets created while exploring the capabilities
119 * of the scanner.
120 */
121
122 SANE_String_Const source_list[] = {
123 FBF_STR,
124 NULL,
125 NULL,
126 NULL
127 };
128
129 static const SANE_String_Const film_list[] = {
130 SANE_I18N("Positive Film"),
131 SANE_I18N("Negative Film"),
132 SANE_I18N("Positive Slide"),
133 SANE_I18N("Negative Slide"),
134 NULL
135 };
136
137 #define HALFTONE_NONE 0x01
138 #define HALFTONE_TET 0x03
139
140 const int halftone_params[] = {
141 HALFTONE_NONE,
142 0x00,
143 0x10,
144 0x20,
145 0x80,
146 0x90,
147 0xa0,
148 0xb0,
149 HALFTONE_TET,
150 0xc0,
151 0xd0
152 };
153
154 static const SANE_String_Const halftone_list[] = {
155 SANE_I18N("None"),
156 SANE_I18N("Halftone A (Hard Tone)"),
157 SANE_I18N("Halftone B (Soft Tone)"),
158 SANE_I18N("Halftone C (Net Screen)"),
159 NULL
160 };
161
162 static const SANE_String_Const halftone_list_4[] = {
163 SANE_I18N("None"),
164 SANE_I18N("Halftone A (Hard Tone)"),
165 SANE_I18N("Halftone B (Soft Tone)"),
166 SANE_I18N("Halftone C (Net Screen)"),
167 SANE_I18N("Dither A (4x4 Bayer)"),
168 SANE_I18N("Dither B (4x4 Spiral)"),
169 SANE_I18N("Dither C (4x4 Net Screen)"),
170 SANE_I18N("Dither D (8x4 Net Screen)"),
171 NULL
172 };
173
174 static const SANE_String_Const halftone_list_7[] = {
175 SANE_I18N("None"),
176 SANE_I18N("Halftone A (Hard Tone)"),
177 SANE_I18N("Halftone B (Soft Tone)"),
178 SANE_I18N("Halftone C (Net Screen)"),
179 SANE_I18N("Dither A (4x4 Bayer)"),
180 SANE_I18N("Dither B (4x4 Spiral)"),
181 SANE_I18N("Dither C (4x4 Net Screen)"),
182 SANE_I18N("Dither D (8x4 Net Screen)"),
183 SANE_I18N("Text Enhanced Technology"),
184 SANE_I18N("Download pattern A"),
185 SANE_I18N("Download pattern B"),
186 NULL
187 };
188
189 static const SANE_String_Const dropout_list[] = {
190 SANE_I18N("None"),
191 SANE_I18N("Red"),
192 SANE_I18N("Green"),
193 SANE_I18N("Blue"),
194 NULL
195 };
196
197 static const SANE_Bool correction_userdefined[] = {
198 SANE_FALSE,
199 SANE_TRUE,
200 SANE_TRUE,
201 };
202
203 static const SANE_String_Const correction_list[] = {
204 SANE_I18N("None"),
205 SANE_I18N("Built in CCT profile"),
206 SANE_I18N("User defined CCT profile"),
207 NULL
208 };
209
210 enum {
211 CORR_NONE, CORR_AUTO, CORR_USER
212 };
213
214 static const SANE_String_Const cct_mode_list[] = {
215 "Automatic",
216 "Reflective",
217 "Colour negatives",
218 "Monochrome negatives",
219 "Colour positives",
220 NULL
221 };
222
223 enum {
224 CCT_AUTO, CCT_REFLECTIVE, CCT_COLORNEG, CCT_MONONEG,
225 CCT_COLORPOS
226 };
227
228 /*
229 * Gamma correction:
230 * The A and B level scanners work differently than the D level scanners,
231 * therefore I define two different sets of arrays, plus one set of
232 * variables that get set to the actually used params and list arrays at runtime.
233 */
234
235 static int gamma_params_ab[] = {
236 0x01,
237 0x03,
238 0x00,
239 0x10,
240 0x20
241 };
242
243 static const SANE_String_Const gamma_list_ab[] = {
244 SANE_I18N("Default"),
245 SANE_I18N("User defined"),
246 SANE_I18N("High density printing"),
247 SANE_I18N("Low density printing"),
248 SANE_I18N("High contrast printing"),
249 NULL
250 };
251
252 static SANE_Bool gamma_userdefined_ab[] = {
253 SANE_FALSE,
254 SANE_TRUE,
255 SANE_FALSE,
256 SANE_FALSE,
257 SANE_FALSE,
258 };
259
260 static int gamma_params_d[] = {
261 0x03,
262 0x04
263 };
264
265 static const SANE_String_Const gamma_list_d[] = {
266 SANE_I18N("User defined (Gamma=1.0)"),
267 SANE_I18N("User defined (Gamma=1.8)"),
268 NULL
269 };
270
271 static SANE_Bool gamma_userdefined_d[] = {
272 SANE_TRUE,
273 SANE_TRUE
274 };
275
276 static SANE_Bool *gamma_userdefined;
277 int *gamma_params;
278
279 /* Bay list:
280 * this is used for the FilmScan
281 * XXX Add APS loader support
282 */
283
284 static const SANE_String_Const bay_list[] = {
285 "1",
286 "2",
287 "3",
288 "4",
289 "5",
290 "6",
291 NULL
292 };
293
294 /* minimum, maximum, quantization */
295 static const SANE_Range focus_range = { 0, 254, 0 };
296 static const SANE_Range u8_range = { 0, 255, 0 };
297 static const SANE_Range fx_range = { SANE_FIX(-2.0), SANE_FIX(2.0), 0 };
298 static const SANE_Range outline_emphasis_range = { -2, 2, 0 };
299
300 /*
301 * List of pointers to devices - will be dynamically allocated depending
302 * on the number of devices found.
303 */
304 static const SANE_Device **devlist;
305
306
307 /* Some utility functions */
308
309 static size_t
max_string_size(const SANE_String_Const strings[])310 max_string_size(const SANE_String_Const strings[])
311 {
312 size_t size, max_size = 0;
313 int i;
314
315 for (i = 0; strings[i]; i++) {
316 size = strlen(strings[i]) + 1;
317 if (size > max_size)
318 max_size = size;
319 }
320 return max_size;
321 }
322
323 static SANE_Status attach_one_usb(SANE_String_Const devname);
324 static SANE_Status attach_one_net(SANE_String_Const devname);
325
326 static void
print_params(const SANE_Parameters params)327 print_params(const SANE_Parameters params)
328 {
329 DBG(6, "params.format = %d\n", params.format);
330 DBG(6, "params.last_frame = %d\n", params.last_frame);
331 DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line);
332 DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line);
333 DBG(6, "params.lines = %d\n", params.lines);
334 DBG(6, "params.depth = %d\n", params.depth);
335 }
336
337 /*
338 * close_scanner()
339 *
340 * Close the open scanner. Depending on the connection method, a different
341 * close function is called.
342 */
343
344 static void
close_scanner(Epson_Scanner *s)345 close_scanner(Epson_Scanner *s)
346 {
347 int i;
348
349 DBG(7, "%s: fd = %d\n", __func__, s->fd);
350
351 if (s->fd == -1)
352 goto free;
353
354 /* send a request_status. This toggles w_cmd_count and r_cmd_count */
355 if (r_cmd_count % 2)
356 esci_request_status(s, NULL);
357
358 /* request extended status. This toggles w_cmd_count only */
359 if (w_cmd_count % 2)
360 esci_request_extended_status(s, NULL, NULL);
361
362 if (s->hw->connection == SANE_EPSON_NET) {
363 sanei_epson_net_unlock(s);
364 sanei_tcp_close(s->fd);
365 } else if (s->hw->connection == SANE_EPSON_SCSI) {
366 sanei_scsi_close(s->fd);
367 } else if (s->hw->connection == SANE_EPSON_PIO) {
368 sanei_pio_close(s->fd);
369 } else if (s->hw->connection == SANE_EPSON_USB) {
370 sanei_usb_close(s->fd);
371 }
372
373 s->fd = -1;
374
375 free:
376 for (i = 0; i < LINES_SHUFFLE_MAX; i++) {
377 if (s->line_buffer[i] != NULL)
378 free(s->line_buffer[i]);
379 }
380
381 free(s);
382 }
383
384 static void
e2_network_discovery(void)385 e2_network_discovery(void)
386 {
387 fd_set rfds;
388 int fd, len;
389 SANE_Status status;
390
391 char *ip, *query = "EPSONP\x00\xff\x00\x00\x00\x00\x00\x00\x00";
392 unsigned char buf[76];
393
394 struct timeval to;
395
396 status = sanei_udp_open_broadcast(&fd);
397 if (status != SANE_STATUS_GOOD)
398 return;
399
400 sanei_udp_write_broadcast(fd, 3289, (unsigned char *) query, 15);
401
402 DBG(5, "%s, sent discovery packet\n", __func__);
403
404 to.tv_sec = 1;
405 to.tv_usec = 0;
406
407 FD_ZERO(&rfds);
408 FD_SET(fd, &rfds);
409
410 sanei_udp_set_nonblock(fd, SANE_TRUE);
411 while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) {
412 if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) {
413 DBG(5, " response from %s\n", ip);
414
415 /* minimal check, protocol unknown */
416 if (strncmp((char *) buf, "EPSON", 5) == 0)
417 attach_one_net(ip);
418 }
419 }
420
421 DBG(5, "%s, end\n", __func__);
422
423 sanei_udp_close(fd);
424 }
425
426 /*
427 * open_scanner()
428 *
429 * Open the scanner device. Depending on the connection method,
430 * different open functions are called.
431 */
432
433 static SANE_Status
open_scanner(Epson_Scanner *s)434 open_scanner(Epson_Scanner *s)
435 {
436 SANE_Status status = 0;
437
438 DBG(7, "%s: %s\n", __func__, s->hw->sane.name);
439
440 if (s->fd != -1) {
441 DBG(5, "scanner is already open: fd = %d\n", s->fd);
442 return SANE_STATUS_GOOD; /* no need to open the scanner */
443 }
444
445 if (s->hw->connection == SANE_EPSON_NET) {
446 unsigned char buf[5];
447
448 /* device name has the form net:ipaddr */
449 status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd);
450 if (status == SANE_STATUS_GOOD) {
451
452 ssize_t read;
453 struct timeval tv;
454
455 tv.tv_sec = 5;
456 tv.tv_usec = 0;
457
458 setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
459
460 s->netlen = 0;
461
462 DBG(32, "awaiting welcome message\n");
463
464 /* the scanner sends a kind of welcome msg */
465 read = e2_recv(s, buf, 5, &status);
466 if (read != 5) {
467 sanei_tcp_close(s->fd);
468 s->fd = -1;
469 return SANE_STATUS_IO_ERROR;
470 }
471
472 DBG(32, "welcome message received, locking the scanner...\n");
473
474 /* lock the scanner for use by sane */
475 status = sanei_epson_net_lock(s);
476 if (status != SANE_STATUS_GOOD) {
477 DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name,
478 sane_strstatus(status));
479
480 sanei_tcp_close(s->fd);
481 s->fd = -1;
482
483 return status;
484 }
485
486 DBG(32, "scanner locked\n");
487 }
488
489 } else if (s->hw->connection == SANE_EPSON_SCSI)
490 status = sanei_scsi_open(s->hw->sane.name, &s->fd,
491 sanei_epson2_scsi_sense_handler,
492 NULL);
493 else if (s->hw->connection == SANE_EPSON_PIO)
494 /* device name has the form pio:0xnnn */
495 status = sanei_pio_open(&s->hw->sane.name[4], &s->fd);
496
497 else if (s->hw->connection == SANE_EPSON_USB)
498 status = sanei_usb_open(s->hw->sane.name, &s->fd);
499
500 if (status == SANE_STATUS_ACCESS_DENIED) {
501 DBG(1, "please check that you have permissions on the device.\n");
502 DBG(1, "if this is a multi-function device with a printer,\n");
503 DBG(1, "disable any conflicting driver (like usblp).\n");
504 }
505
506 if (status != SANE_STATUS_GOOD)
507 DBG(1, "%s open failed: %s\n", s->hw->sane.name,
508 sane_strstatus(status));
509 else
510 DBG(5, "scanner opened\n");
511
512 return status;
513 }
514
detect_scsi(struct Epson_Scanner *s)515 static SANE_Status detect_scsi(struct Epson_Scanner *s)
516 {
517 SANE_Status status;
518 struct Epson_Device *dev = s->hw;
519
520 char buf[INQUIRY_BUF_SIZE + 1];
521 size_t buf_size = INQUIRY_BUF_SIZE;
522
523 char *vendor = buf + 8;
524 char *model = buf + 16;
525 char *rev = buf + 32;
526
527 status = sanei_epson2_scsi_inquiry(s->fd, buf, &buf_size);
528 if (status != SANE_STATUS_GOOD) {
529 DBG(1, "%s: inquiry failed: %s\n", __func__,
530 sane_strstatus(status));
531 return status;
532 }
533
534 buf[INQUIRY_BUF_SIZE] = 0;
535 DBG(1, "inquiry data:\n");
536 DBG(1, " vendor : %.8s\n", vendor);
537 DBG(1, " model : %.16s\n", model);
538 DBG(1, " revision: %.4s\n", rev);
539
540 if (buf[0] != TYPE_PROCESSOR) {
541 DBG(1, "%s: device is not of processor type (%d)\n",
542 __func__, buf[0]);
543 return SANE_STATUS_INVAL;
544 }
545
546 if (strncmp(vendor, "EPSON", 5) != 0) {
547 DBG(1,
548 "%s: device doesn't look like an EPSON scanner\n",
549 __func__);
550 return SANE_STATUS_INVAL;
551 }
552
553 if (strncmp(model, "SCANNER ", 8) != 0
554 && strncmp(model, "FilmScan 200", 12) != 0
555 && strncmp(model, "Perfection", 10) != 0
556 && strncmp(model, "Expression", 10) != 0
557 && strncmp(model, "GT", 2) != 0) {
558 DBG(1, "%s: this EPSON scanner is not supported\n",
559 __func__);
560 return SANE_STATUS_INVAL;
561 }
562
563 if (strncmp(model, "FilmScan 200", 12) == 0) {
564 dev->sane.type = "film scanner";
565 e2_set_model(s, (unsigned char *) model, 12);
566 }
567
568 /* Issue a test unit ready SCSI command. The FilmScan 200
569 * requires it for a sort of "wake up". We might eventually
570 * get the return code and reissue it in case of failure.
571 */
572 sanei_epson2_scsi_test_unit_ready(s->fd);
573
574 return SANE_STATUS_GOOD;
575 }
576
577 static SANE_Status
detect_usb(struct Epson_Scanner *s, SANE_Bool assume_valid)578 detect_usb(struct Epson_Scanner *s, SANE_Bool assume_valid)
579 {
580 SANE_Status status;
581 int vendor, product;
582 int i, numIds;
583 SANE_Bool is_valid = assume_valid;
584
585 /* if the sanei_usb_get_vendor_product call is not supported,
586 * then we just ignore this and rely on the user to config
587 * the correct device.
588 */
589
590 status = sanei_usb_get_vendor_product(s->fd, &vendor, &product);
591 if (status != SANE_STATUS_GOOD) {
592 DBG(1, "the device cannot be verified - will continue\n");
593 return SANE_STATUS_GOOD;
594 }
595
596 /* check the vendor ID to see if we are dealing with an EPSON device */
597 if (vendor != SANE_EPSON_VENDOR_ID) {
598 /* this is not a supported vendor ID */
599 DBG(1, "not an Epson device at %s (vendor id=0x%x)\n",
600 s->hw->sane.name, vendor);
601 return SANE_STATUS_INVAL;
602 }
603
604 numIds = sanei_epson_getNumberOfUSBProductIds();
605 i = 0;
606
607 /* check all known product IDs to verify that we know
608 about the device */
609 while (i != numIds) {
610 if (product == sanei_epson_usb_product_ids[i]) {
611 is_valid = SANE_TRUE;
612 break;
613 }
614 i++;
615 }
616
617 if (is_valid == SANE_FALSE) {
618 DBG(1, "the device at %s is not supported (product id=0x%x)\n",
619 s->hw->sane.name, product);
620 return SANE_STATUS_INVAL;
621 }
622
623 DBG(1, "found valid Epson scanner: 0x%x/0x%x (vendorID/productID)\n",
624 vendor, product);
625
626 return SANE_STATUS_GOOD;
627 }
628
629 static int num_devices; /* number of scanners attached to backend */
630 static Epson_Device *first_dev; /* first EPSON scanner in list */
631
632 static struct Epson_Scanner *
scanner_create(struct Epson_Device *dev, SANE_Status *status)633 scanner_create(struct Epson_Device *dev, SANE_Status *status)
634 {
635 struct Epson_Scanner *s;
636
637 s = malloc(sizeof(struct Epson_Scanner));
638 if (s == NULL) {
639 *status = SANE_STATUS_NO_MEM;
640 return NULL;
641 }
642
643 memset(s, 0x00, sizeof(struct Epson_Scanner));
644
645 s->fd = -1;
646 s->hw = dev;
647
648 return s;
649 }
650
651 static struct Epson_Scanner *
device_detect(const char *name, int type, SANE_Bool assume_valid, SANE_Status *status)652 device_detect(const char *name, int type, SANE_Bool assume_valid, SANE_Status *status)
653 {
654 struct Epson_Scanner *s;
655 struct Epson_Device *dev;
656
657 /* try to find the device in our list */
658 for (dev = first_dev; dev; dev = dev->next) {
659 if (strcmp(dev->sane.name, name) == 0) {
660
661 /* the device might have been just probed,
662 * sleep a bit.
663 */
664 if (dev->connection == SANE_EPSON_NET)
665 sleep(1);
666
667 return scanner_create(dev, status);
668 }
669 }
670
671 if (type == SANE_EPSON_NODEV) {
672 *status = SANE_STATUS_INVAL;
673 return NULL;
674 }
675
676 /* alloc and clear our device structure */
677 dev = malloc(sizeof(*dev));
678 if (!dev) {
679 *status = SANE_STATUS_NO_MEM;
680 return NULL;
681 }
682 memset(dev, 0x00, sizeof(struct Epson_Device));
683
684 s = scanner_create(dev, status);
685 if (s == NULL)
686 return NULL;
687
688 e2_dev_init(dev, name, type);
689
690 *status = open_scanner(s);
691 if (*status != SANE_STATUS_GOOD) {
692 free(s);
693 return NULL;
694 }
695
696 /* from now on, close_scanner() must be called */
697
698 /* SCSI and USB requires special care */
699 if (dev->connection == SANE_EPSON_SCSI) {
700
701 *status = detect_scsi(s);
702
703 } else if (dev->connection == SANE_EPSON_USB) {
704
705 *status = detect_usb(s, assume_valid);
706 }
707
708 if (*status != SANE_STATUS_GOOD)
709 goto close;
710
711 /* set name and model (if not already set) */
712 if (dev->model == NULL)
713 e2_set_model(s, (unsigned char *) "generic", 7);
714
715 dev->name = strdup(name);
716 dev->sane.name = dev->name;
717
718 /* ESC @, reset */
719 *status = esci_reset(s);
720 if (*status != SANE_STATUS_GOOD)
721 goto close;
722
723 *status = e2_discover_capabilities(s);
724 if (*status != SANE_STATUS_GOOD)
725 goto close;
726
727 if (source_list[0] == NULL || dev->dpi_range.min == 0) {
728 DBG(1, "something is wrong in the discovery process, aborting.\n");
729 *status = SANE_STATUS_IO_ERROR;
730 goto close;
731 }
732
733 e2_dev_post_init(dev);
734
735 *status = esci_reset(s);
736 if (*status != SANE_STATUS_GOOD)
737 goto close;
738
739 DBG(1, "scanner model: %s\n", dev->model);
740
741 /* add this scanner to the device list */
742
743 num_devices++;
744 dev->next = first_dev;
745 first_dev = dev;
746
747 return s;
748
749 close:
750 close_scanner(s);
751 return NULL;
752 }
753
754
755 static SANE_Status
attach(const char *name, int type)756 attach(const char *name, int type)
757 {
758 SANE_Status status;
759 Epson_Scanner *s;
760
761 DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type);
762
763 s = device_detect(name, type, 0, &status);
764 if(s == NULL)
765 return status;
766
767 close_scanner(s);
768 return status;
769 }
770
771 static SANE_Status
attach_one_scsi(const char *dev)772 attach_one_scsi(const char *dev)
773 {
774 DBG(7, "%s: dev = %s\n", __func__, dev);
775 return attach(dev, SANE_EPSON_SCSI);
776 }
777
778 SANE_Status
attach_one_usb(const char *dev)779 attach_one_usb(const char *dev)
780 {
781 DBG(7, "%s: dev = %s\n", __func__, dev);
782 return attach(dev, SANE_EPSON_USB);
783 }
784
785 static SANE_Status
attach_one_net(const char *dev)786 attach_one_net(const char *dev)
787 {
788 char name[39+4];
789
790 DBG(7, "%s: dev = %s\n", __func__, dev);
791
792 strcpy(name, "net:");
793 strcat(name, dev);
794 return attach(name, SANE_EPSON_NET);
795 }
796
797 static SANE_Status
attach_one_pio(const char *dev)798 attach_one_pio(const char *dev)
799 {
800 DBG(7, "%s: dev = %s\n", __func__, dev);
801 return attach(dev, SANE_EPSON_PIO);
802 }
803
804 static SANE_Status
attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, void *data)805 attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
806 void *data)
807 {
808 int vendor, product;
809 SANE_Bool local_only = *(SANE_Bool*) data;
810 int len = strlen(line);
811
812 DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
813
814 if (sscanf(line, "usb %i %i", &vendor, &product) == 2) {
815
816 /* add the vendor and product IDs to the list of
817 known devices before we call the attach function */
818
819 int numIds = sanei_epson_getNumberOfUSBProductIds();
820
821 if (vendor != 0x4b8)
822 return SANE_STATUS_INVAL; /* this is not an EPSON device */
823
824 sanei_epson_usb_product_ids[numIds - 1] = product;
825 sanei_usb_attach_matching_devices(line, attach_one_usb);
826
827 } else if (strncmp(line, "usb", 3) == 0 && len == 3) {
828
829 int i, numIds;
830
831 numIds = sanei_epson_getNumberOfUSBProductIds();
832
833 for (i = 0; i < numIds; i++) {
834 sanei_usb_find_devices(0x4b8,
835 sanei_epson_usb_product_ids[i], attach_one_usb);
836 }
837
838 } else if (strncmp(line, "net", 3) == 0) {
839
840 if (!local_only) {
841 /* remove the "net" sub string */
842 const char *name =
843 sanei_config_skip_whitespace(line + 3);
844
845 if (strncmp(name, "autodiscovery", 13) == 0)
846 e2_network_discovery();
847 else
848 attach_one_net(name);
849 }
850
851 } else if (strncmp(line, "pio", 3) == 0) {
852
853 /* remove the "pio" sub string */
854 const char *name = sanei_config_skip_whitespace(line + 3);
855
856 attach_one_pio(name);
857
858 } else {
859 sanei_config_attach_matching_devices(line, attach_one_scsi);
860 }
861
862 return SANE_STATUS_GOOD;
863 }
864
865 static void
free_devices(void)866 free_devices(void)
867 {
868 Epson_Device *dev, *next;
869
870 DBG(5, "%s\n", __func__);
871
872 for (dev = first_dev; dev; dev = next) {
873 next = dev->next;
874 free(dev->name);
875 free(dev->model);
876 free(dev);
877 }
878
879 free(devlist);
880
881 first_dev = NULL;
882 }
883
884 static void
probe_devices(SANE_Bool local_only)885 probe_devices(SANE_Bool local_only)
886 {
887 DBG(5, "%s\n", __func__);
888
889 free_devices();
890
891 sanei_configure_attach(EPSON2_CONFIG_FILE, NULL,
892 attach_one_config, &local_only);
893 }
894
895 SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)896 sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize)
897 {
898 DBG_INIT();
899 DBG(1, "%s: version " VERSION "\n", __func__);
900
901 /* Keep '124' as our build version. The arg is obsolete by now */
902 if (version_code)
903 *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 124);
904
905 sanei_usb_init();
906 sanei_usb_set_timeout(60 * 1000);
907
908 return SANE_STATUS_GOOD;
909 }
910
911 /* Clean up the list of attached scanners. */
912 void
sane_exit(void)913 sane_exit(void)
914 {
915 DBG(5, "%s\n", __func__);
916 free_devices();
917 }
918
919 SANE_Status
sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)920 sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
921 {
922 Epson_Device *dev;
923 int i;
924
925 DBG(5, "%s\n", __func__);
926
927 probe_devices(local_only);
928
929 devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
930 if (!devlist) {
931 DBG(1, "out of memory (line %d)\n", __LINE__);
932 return SANE_STATUS_NO_MEM;
933 }
934
935 DBG(5, "%s - results:\n", __func__);
936
937 for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) {
938 DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model);
939 devlist[i] = &dev->sane;
940 }
941
942 devlist[i] = NULL;
943
944 *device_list = devlist;
945
946 return SANE_STATUS_GOOD;
947 }
948
949 static SANE_Status
init_options(Epson_Scanner *s)950 init_options(Epson_Scanner *s)
951 {
952 int i;
953
954 for (i = 0; i < NUM_OPTIONS; i++) {
955 s->opt[i].size = sizeof(SANE_Word);
956 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
957 }
958
959 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
960 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
961 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
962 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
963 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
964
965 /* "Scan Mode" group: */
966
967 s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
968 s->opt[OPT_MODE_GROUP].desc = "";
969 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
970 s->opt[OPT_MODE_GROUP].cap = 0;
971
972 /* scan mode */
973 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
974 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
975 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
976 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
977 s->opt[OPT_MODE].size = max_string_size(mode_list);
978 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
979 s->opt[OPT_MODE].constraint.string_list = mode_list;
980 s->val[OPT_MODE].w = 0; /* Lineart */
981
982 /* disable infrared on unsupported scanners */
983 if (!e2_model(s, "GT-X800") && !e2_model(s, "GT-X700") && !e2_model(s, "GT-X900") && !e2_model(s, "GT-X980"))
984 mode_list[MODE_INFRARED] = NULL;
985
986 /* bit depth */
987 s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
988 s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
989 s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
990 s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
991 s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT;
992 s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
993 s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->depth_list;
994 s->val[OPT_BIT_DEPTH].w = 8; /* default to 8 bit */
995
996 /* default is Lineart, disable depth selection */
997 s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
998
999 /* halftone */
1000 s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE;
1001 s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE;
1002 s->opt[OPT_HALFTONE].desc = SANE_I18N("Selects the halftone.");
1003
1004 s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING;
1005 s->opt[OPT_HALFTONE].size = max_string_size(halftone_list_7);
1006 s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1007
1008 /* XXX use defines */
1009 if (s->hw->level >= 7)
1010 s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_7;
1011 else if (s->hw->level >= 4)
1012 s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_4;
1013 else
1014 s->opt[OPT_HALFTONE].constraint.string_list = halftone_list;
1015
1016 s->val[OPT_HALFTONE].w = 1; /* Halftone A */
1017
1018 if (!s->hw->cmd->set_halftoning)
1019 s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
1020
1021 /* dropout */
1022 s->opt[OPT_DROPOUT].name = "dropout";
1023 s->opt[OPT_DROPOUT].title = SANE_I18N("Dropout");
1024 s->opt[OPT_DROPOUT].desc = SANE_I18N("Selects the dropout.");
1025
1026 s->opt[OPT_DROPOUT].type = SANE_TYPE_STRING;
1027 s->opt[OPT_DROPOUT].size = max_string_size(dropout_list);
1028 s->opt[OPT_DROPOUT].cap |= SANE_CAP_ADVANCED;
1029 s->opt[OPT_DROPOUT].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1030 s->opt[OPT_DROPOUT].constraint.string_list = dropout_list;
1031 s->val[OPT_DROPOUT].w = 0; /* None */
1032
1033 /* brightness */
1034 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
1035 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
1036 s->opt[OPT_BRIGHTNESS].desc = SANE_I18N("Selects the brightness.");
1037
1038 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
1039 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
1040 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1041 s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cmd->bright_range;
1042 s->val[OPT_BRIGHTNESS].w = 0; /* Normal */
1043
1044 if (!s->hw->cmd->set_bright)
1045 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
1046
1047 /* sharpness */
1048 s->opt[OPT_SHARPNESS].name = "sharpness";
1049 s->opt[OPT_SHARPNESS].title = SANE_I18N("Sharpness");
1050 s->opt[OPT_SHARPNESS].desc = "";
1051
1052 s->opt[OPT_SHARPNESS].type = SANE_TYPE_INT;
1053 s->opt[OPT_SHARPNESS].unit = SANE_UNIT_NONE;
1054 s->opt[OPT_SHARPNESS].constraint_type = SANE_CONSTRAINT_RANGE;
1055 s->opt[OPT_SHARPNESS].constraint.range = &outline_emphasis_range;
1056 s->val[OPT_SHARPNESS].w = 0; /* Normal */
1057
1058 if (!s->hw->cmd->set_outline_emphasis)
1059 s->opt[OPT_SHARPNESS].cap |= SANE_CAP_INACTIVE;
1060
1061 /* gamma */
1062 s->opt[OPT_GAMMA_CORRECTION].name = SANE_NAME_GAMMA_CORRECTION;
1063 s->opt[OPT_GAMMA_CORRECTION].title = SANE_TITLE_GAMMA_CORRECTION;
1064 s->opt[OPT_GAMMA_CORRECTION].desc = SANE_DESC_GAMMA_CORRECTION;
1065
1066 s->opt[OPT_GAMMA_CORRECTION].type = SANE_TYPE_STRING;
1067 s->opt[OPT_GAMMA_CORRECTION].constraint_type =
1068 SANE_CONSTRAINT_STRING_LIST;
1069
1070 /*
1071 * special handling for D1 function level - at this time I'm not
1072 * testing for D1, I'm just assuming that all D level scanners will
1073 * behave the same way. This has to be confirmed with the next D-level
1074 * scanner
1075 */
1076 if (s->hw->cmd->level[0] == 'D') {
1077 s->opt[OPT_GAMMA_CORRECTION].size =
1078 max_string_size(gamma_list_d);
1079 s->opt[OPT_GAMMA_CORRECTION].constraint.string_list =
1080 gamma_list_d;
1081 s->val[OPT_GAMMA_CORRECTION].w = 1; /* Default */
1082 gamma_userdefined = gamma_userdefined_d;
1083 gamma_params = gamma_params_d;
1084 } else {
1085 s->opt[OPT_GAMMA_CORRECTION].size =
1086 max_string_size(gamma_list_ab);
1087 s->opt[OPT_GAMMA_CORRECTION].constraint.string_list =
1088 gamma_list_ab;
1089 s->val[OPT_GAMMA_CORRECTION].w = 0; /* Default */
1090 gamma_userdefined = gamma_userdefined_ab;
1091 gamma_params = gamma_params_ab;
1092 }
1093
1094 if (!s->hw->cmd->set_gamma)
1095 s->opt[OPT_GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE;
1096
1097 /* red gamma vector */
1098 s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
1099 s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
1100 s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
1101
1102 s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
1103 s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
1104 s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof(SANE_Word);
1105 s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
1106 s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
1107 s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0];
1108
1109 /* green gamma vector */
1110 s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
1111 s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
1112 s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
1113
1114 s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
1115 s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
1116 s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof(SANE_Word);
1117 s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
1118 s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
1119 s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0];
1120
1121
1122 /* red gamma vector */
1123 s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
1124 s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
1125 s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
1126
1127 s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
1128 s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
1129 s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof(SANE_Word);
1130 s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
1131 s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
1132 s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0];
1133
1134 if (s->hw->cmd->set_gamma_table
1135 && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w] ==
1136 SANE_TRUE) {
1137
1138 s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
1139 s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
1140 s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
1141 } else {
1142
1143 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
1144 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
1145 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
1146 }
1147
1148 /* initialize the Gamma tables */
1149 memset(&s->gamma_table[0], 0, 256 * sizeof(SANE_Word));
1150 memset(&s->gamma_table[1], 0, 256 * sizeof(SANE_Word));
1151 memset(&s->gamma_table[2], 0, 256 * sizeof(SANE_Word));
1152
1153 /* memset(&s->gamma_table[3], 0, 256 * sizeof(SANE_Word)); */
1154 for (i = 0; i < 256; i++) {
1155 s->gamma_table[0][i] = i;
1156 s->gamma_table[1][i] = i;
1157 s->gamma_table[2][i] = i;
1158
1159 /* s->gamma_table[3][i] = i; */
1160 }
1161
1162
1163 /* color correction */
1164 s->opt[OPT_COLOR_CORRECTION].name = "color-correction";
1165 s->opt[OPT_COLOR_CORRECTION].title = SANE_I18N("Color correction");
1166 s->opt[OPT_COLOR_CORRECTION].desc =
1167 SANE_I18N("Sets the color correction table for the selected output device.");
1168
1169 s->opt[OPT_COLOR_CORRECTION].type = SANE_TYPE_STRING;
1170 s->opt[OPT_COLOR_CORRECTION].size = max_string_size(correction_list);
1171 s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_ADVANCED;
1172 s->opt[OPT_COLOR_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1173 s->opt[OPT_COLOR_CORRECTION].constraint.string_list = correction_list;
1174 s->val[OPT_COLOR_CORRECTION].w = CORR_AUTO;
1175
1176 if (!s->hw->cmd->set_color_correction)
1177 s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_INACTIVE;
1178
1179 /* resolution */
1180 s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
1181 s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
1182 s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
1183
1184 s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
1185 s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
1186 s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
1187 s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->resolution_list;
1188 s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min;
1189
1190 /* threshold */
1191 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
1192 s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
1193 s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
1194
1195 s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
1196 s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
1197 s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
1198 s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
1199 s->val[OPT_THRESHOLD].w = 0x80;
1200
1201 if (!s->hw->cmd->set_threshold)
1202 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
1203
1204
1205 /* "Advanced" group: */
1206 s->opt[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced");
1207 s->opt[OPT_ADVANCED_GROUP].desc = "";
1208 s->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
1209 s->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
1210
1211 /* "Color correction" group: */
1212 s->opt[OPT_CCT_GROUP].title = SANE_I18N("Color correction");
1213 s->opt[OPT_CCT_GROUP].desc = "";
1214 s->opt[OPT_CCT_GROUP].type = SANE_TYPE_GROUP;
1215 s->opt[OPT_CCT_GROUP].cap = SANE_CAP_ADVANCED;
1216
1217 /* XXX disabled for now */
1218 s->opt[OPT_CCT_MODE].name = "cct-type";
1219 s->opt[OPT_CCT_MODE].title = "CCT Profile Type";
1220 s->opt[OPT_CCT_MODE].desc = "Color correction profile type";
1221 s->opt[OPT_CCT_MODE].type = SANE_TYPE_STRING;
1222 s->opt[OPT_CCT_MODE].cap |= SANE_CAP_ADVANCED | SANE_CAP_INACTIVE;
1223 s->opt[OPT_CCT_MODE].size = max_string_size(cct_mode_list);
1224 s->opt[OPT_CCT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1225 s->opt[OPT_CCT_MODE].constraint.string_list = cct_mode_list;
1226 s->val[OPT_CCT_MODE].w = CCT_AUTO;
1227
1228 s->opt[OPT_CCT_PROFILE].name = "cct-profile";
1229 s->opt[OPT_CCT_PROFILE].title = "CCT Profile";
1230 s->opt[OPT_CCT_PROFILE].desc = "Color correction profile data";
1231 s->opt[OPT_CCT_PROFILE].type = SANE_TYPE_FIXED;
1232 s->opt[OPT_CCT_PROFILE].cap |= SANE_CAP_ADVANCED;
1233 s->opt[OPT_CCT_PROFILE].unit = SANE_UNIT_NONE;
1234 s->opt[OPT_CCT_PROFILE].constraint_type = SANE_CONSTRAINT_RANGE;
1235 s->opt[OPT_CCT_PROFILE].constraint.range = &fx_range;
1236 s->opt[OPT_CCT_PROFILE].size = 9 * sizeof(SANE_Word);
1237 s->val[OPT_CCT_PROFILE].wa = s->cct_table;
1238
1239 /* if (!s->hw->cmd->set_color_correction)
1240 s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE;
1241 */
1242
1243 /* mirror */
1244 s->opt[OPT_MIRROR].name = "mirror";
1245 s->opt[OPT_MIRROR].title = SANE_I18N("Mirror image");
1246 s->opt[OPT_MIRROR].desc = SANE_I18N("Mirror the image.");
1247
1248 s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL;
1249 s->val[OPT_MIRROR].w = SANE_FALSE;
1250
1251 if (!s->hw->cmd->mirror_image)
1252 s->opt[OPT_MIRROR].cap |= SANE_CAP_INACTIVE;
1253
1254 /* auto area segmentation */
1255 s->opt[OPT_AAS].name = "auto-area-segmentation";
1256 s->opt[OPT_AAS].title = SANE_I18N("Auto area segmentation");
1257 s->opt[OPT_AAS].desc =
1258 "Enables different dithering modes in image and text areas";
1259
1260 s->opt[OPT_AAS].type = SANE_TYPE_BOOL;
1261 s->val[OPT_AAS].w = SANE_TRUE;
1262
1263 if (!s->hw->cmd->control_auto_area_segmentation)
1264 s->opt[OPT_AAS].cap |= SANE_CAP_INACTIVE;
1265
1266 /* "Preview settings" group: */
1267 s->opt[OPT_PREVIEW_GROUP].title = SANE_TITLE_PREVIEW;
1268 s->opt[OPT_PREVIEW_GROUP].desc = "";
1269 s->opt[OPT_PREVIEW_GROUP].type = SANE_TYPE_GROUP;
1270 s->opt[OPT_PREVIEW_GROUP].cap = SANE_CAP_ADVANCED;
1271
1272 /* preview */
1273 s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
1274 s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
1275 s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
1276
1277 s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
1278 s->val[OPT_PREVIEW].w = SANE_FALSE;
1279
1280 /* "Geometry" group: */
1281 s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry");
1282 s->opt[OPT_GEOMETRY_GROUP].desc = "";
1283 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
1284 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
1285
1286 /* top-left x */
1287 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
1288 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
1289 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
1290
1291 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
1292 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
1293 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
1294 s->opt[OPT_TL_X].constraint.range = s->hw->x_range;
1295 s->val[OPT_TL_X].w = 0;
1296
1297 /* top-left y */
1298 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
1299 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
1300 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
1301
1302 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
1303 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
1304 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1305 s->opt[OPT_TL_Y].constraint.range = s->hw->y_range;
1306 s->val[OPT_TL_Y].w = 0;
1307
1308 /* bottom-right x */
1309 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
1310 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
1311 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
1312
1313 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
1314 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
1315 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
1316 s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
1317 s->val[OPT_BR_X].w = s->hw->x_range->max;
1318
1319 /* bottom-right y */
1320 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
1321 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
1322 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
1323
1324 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
1325 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
1326 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
1327 s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
1328 s->val[OPT_BR_Y].w = s->hw->y_range->max;
1329
1330 /* "Focus" group: */
1331 s->opt[OPT_FOCUS_GROUP].title = SANE_I18N("Focus");
1332 s->opt[OPT_FOCUS_GROUP].desc = "";
1333 s->opt[OPT_FOCUS_GROUP].type = SANE_TYPE_GROUP;
1334 s->opt[OPT_FOCUS_GROUP].cap = SANE_CAP_ADVANCED;
1335
1336 /* autofocus */
1337 s->opt[OPT_AUTOFOCUS].name = SANE_NAME_AUTOFOCUS;
1338 s->opt[OPT_AUTOFOCUS].title = SANE_TITLE_AUTOFOCUS;
1339 s->opt[OPT_AUTOFOCUS].desc = SANE_DESC_AUTOFOCUS;
1340 s->opt[OPT_AUTOFOCUS].type = SANE_TYPE_BOOL;
1341 s->val[OPT_AUTOFOCUS].w = SANE_FALSE;
1342 s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_ADVANCED;
1343
1344 /* focus position */
1345 s->opt[OPT_FOCUS_POS].name = SANE_NAME_FOCUS;
1346 s->opt[OPT_FOCUS_POS].title = SANE_TITLE_FOCUS;
1347 s->opt[OPT_FOCUS_POS].desc = SANE_DESC_FOCUS;
1348 s->opt[OPT_FOCUS_POS].type = SANE_TYPE_INT;
1349 s->opt[OPT_FOCUS_POS].unit = SANE_UNIT_NONE;
1350 s->opt[OPT_FOCUS_POS].constraint_type = SANE_CONSTRAINT_RANGE;
1351 s->opt[OPT_FOCUS_POS].constraint.range = &focus_range;
1352 s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
1353 s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_ADVANCED;
1354
1355 if (s->hw->focusSupport == SANE_TRUE) {
1356 s->opt[OPT_FOCUS_POS].cap &= ~SANE_CAP_INACTIVE;
1357 s->opt[OPT_AUTOFOCUS].cap &= ~SANE_CAP_INACTIVE;
1358 } else {
1359 s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_INACTIVE;
1360 s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_INACTIVE;
1361 }
1362
1363 /* "Optional equipment" group: */
1364 s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment");
1365 s->opt[OPT_EQU_GROUP].desc = "";
1366 s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP;
1367 s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED;
1368
1369 /* source */
1370 s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
1371 s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
1372 s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
1373
1374 s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
1375 s->opt[OPT_SOURCE].size = max_string_size(source_list);
1376
1377 s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1378 s->opt[OPT_SOURCE].constraint.string_list = source_list;
1379
1380 if (!s->hw->extension)
1381 s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE;
1382
1383 s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */
1384
1385
1386 /* film type */
1387 s->opt[OPT_FILM_TYPE].name = "film-type";
1388 s->opt[OPT_FILM_TYPE].title = SANE_I18N("Film type");
1389 s->opt[OPT_FILM_TYPE].desc = "";
1390 s->opt[OPT_FILM_TYPE].type = SANE_TYPE_STRING;
1391 s->opt[OPT_FILM_TYPE].size = max_string_size(film_list);
1392 s->opt[OPT_FILM_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1393 s->opt[OPT_FILM_TYPE].constraint.string_list = film_list;
1394 s->val[OPT_FILM_TYPE].w = 0;
1395
1396 if (!s->hw->cmd->set_bay)
1397 s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE;
1398
1399 /* forward feed / eject */
1400 s->opt[OPT_EJECT].name = "eject";
1401 s->opt[OPT_EJECT].title = SANE_I18N("Eject");
1402 s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF");
1403 s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON;
1404
1405 if ((!s->hw->ADF) && (!s->hw->cmd->set_bay)) { /* Hack: Using set_bay to indicate. */
1406 s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE;
1407 }
1408
1409
1410 /* auto forward feed / eject */
1411 s->opt[OPT_AUTO_EJECT].name = "auto-eject";
1412 s->opt[OPT_AUTO_EJECT].title = SANE_I18N("Auto eject");
1413 s->opt[OPT_AUTO_EJECT].desc =
1414 SANE_I18N("Eject document after scanning");
1415
1416 s->opt[OPT_AUTO_EJECT].type = SANE_TYPE_BOOL;
1417 s->val[OPT_AUTO_EJECT].w = SANE_FALSE;
1418
1419 if (!s->hw->ADF)
1420 s->opt[OPT_AUTO_EJECT].cap |= SANE_CAP_INACTIVE;
1421
1422
1423 s->opt[OPT_ADF_MODE].name = "adf-mode";
1424 s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode");
1425 s->opt[OPT_ADF_MODE].desc =
1426 SANE_I18N("Selects the ADF mode (simplex/duplex)");
1427 s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING;
1428 s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list);
1429 s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1430 s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list;
1431 s->val[OPT_ADF_MODE].w = 0; /* simplex */
1432
1433 if ((!s->hw->ADF) || (s->hw->duplex == SANE_FALSE))
1434 s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE;
1435
1436 /* select bay */
1437 s->opt[OPT_BAY].name = "bay";
1438 s->opt[OPT_BAY].title = SANE_I18N("Bay");
1439 s->opt[OPT_BAY].desc = SANE_I18N("Select bay to scan");
1440 s->opt[OPT_BAY].type = SANE_TYPE_STRING;
1441 s->opt[OPT_BAY].size = max_string_size(bay_list);
1442 s->opt[OPT_BAY].constraint_type = SANE_CONSTRAINT_STRING_LIST;
1443 s->opt[OPT_BAY].constraint.string_list = bay_list;
1444 s->val[OPT_BAY].w = 0; /* Bay 1 */
1445
1446 if (!s->hw->cmd->set_bay)
1447 s->opt[OPT_BAY].cap |= SANE_CAP_INACTIVE;
1448
1449
1450 s->opt[OPT_WAIT_FOR_BUTTON].name = SANE_EPSON_WAIT_FOR_BUTTON_NAME;
1451 s->opt[OPT_WAIT_FOR_BUTTON].title = SANE_EPSON_WAIT_FOR_BUTTON_TITLE;
1452 s->opt[OPT_WAIT_FOR_BUTTON].desc = SANE_EPSON_WAIT_FOR_BUTTON_DESC;
1453
1454 s->opt[OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL;
1455 s->opt[OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE;
1456 s->opt[OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE;
1457 s->opt[OPT_WAIT_FOR_BUTTON].constraint.range = NULL;
1458 s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_ADVANCED;
1459
1460 if (!s->hw->cmd->request_push_button_status)
1461 s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_INACTIVE;
1462
1463 return SANE_STATUS_GOOD;
1464 }
1465
1466 SANE_Status
sane_open(SANE_String_Const name, SANE_Handle *handle)1467 sane_open(SANE_String_Const name, SANE_Handle *handle)
1468 {
1469 SANE_Status status;
1470 Epson_Scanner *s = NULL;
1471
1472 int l = strlen(name);
1473
1474 DBG(7, "%s: name = %s\n", __func__, name);
1475
1476 *handle = NULL;
1477
1478 /* probe if empty device name provided */
1479 if (l == 0) {
1480
1481 probe_devices(SANE_FALSE);
1482
1483 if (first_dev == NULL) {
1484 DBG(1, "no device detected\n");
1485 return SANE_STATUS_INVAL;
1486 }
1487
1488 s = device_detect(first_dev->sane.name, first_dev->connection,
1489 0, &status);
1490 if (s == NULL) {
1491 DBG(1, "cannot open a perfectly valid device (%s),"
1492 " please report to the authors\n", name);
1493 return SANE_STATUS_INVAL;
1494 }
1495
1496 } else {
1497
1498 if (strncmp(name, "net:", 4) == 0) {
1499 s = device_detect(name, SANE_EPSON_NET, 0, &status);
1500 if (s == NULL)
1501 return status;
1502 } else if (strncmp(name, "libusb:", 7) == 0) {
1503 s = device_detect(name, SANE_EPSON_USB, 1, &status);
1504 if (s == NULL)
1505 return status;
1506 } else if (strncmp(name, "pio:", 4) == 0) {
1507 s = device_detect(name, SANE_EPSON_PIO, 0, &status);
1508 if (s == NULL)
1509 return status;
1510 } else {
1511
1512 /* as a last resort, check for a match
1513 * in the device list. This should handle SCSI
1514 * devices and platforms without libusb.
1515 */
1516
1517 if (first_dev == NULL)
1518 probe_devices(SANE_FALSE);
1519
1520 s = device_detect(name, SANE_EPSON_NODEV, 0, &status);
1521 if (s == NULL) {
1522 DBG(1, "invalid device name: %s\n", name);
1523 return SANE_STATUS_INVAL;
1524 }
1525 }
1526 }
1527
1528
1529 /* s is always valid here */
1530
1531 DBG(1, "handle obtained\n");
1532
1533 init_options(s);
1534
1535 status = open_scanner(s);
1536 if (status != SANE_STATUS_GOOD) {
1537 free(s);
1538 return status;
1539 }
1540
1541 status = esci_reset(s);
1542 if (status != SANE_STATUS_GOOD) {
1543 close_scanner(s);
1544 return status;
1545 }
1546
1547 *handle = (SANE_Handle)s;
1548
1549 return SANE_STATUS_GOOD;
1550 }
1551
1552 void
sane_close(SANE_Handle handle)1553 sane_close(SANE_Handle handle)
1554 {
1555 Epson_Scanner *s;
1556
1557 DBG(1, "* %s\n", __func__);
1558
1559 /*
1560 * XXX Test if there is still data pending from
1561 * the scanner. If so, then do a cancel
1562 */
1563
1564 s = (Epson_Scanner *) handle;
1565
1566 close_scanner(s);
1567 }
1568
1569 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)1570 sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
1571 {
1572 Epson_Scanner *s = (Epson_Scanner *) handle;
1573
1574 if (option < 0 || option >= NUM_OPTIONS)
1575 return NULL;
1576
1577 return s->opt + option;
1578 }
1579
1580 static const SANE_String_Const *
search_string_list(const SANE_String_Const *list, SANE_String value)1581 search_string_list(const SANE_String_Const *list, SANE_String value)
1582 {
1583 while (*list != NULL && strcmp(value, *list) != 0)
1584 list++;
1585
1586 return ((*list == NULL) ? NULL : list);
1587 }
1588
1589 /*
1590 Activate, deactivate an option. Subroutines so we can add
1591 debugging info if we want. The change flag is set to TRUE
1592 if we changed an option. If we did not change an option,
1593 then the value of the changed flag is not modified.
1594 */
1595
1596 static void
activateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change)1597 activateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change)
1598 {
1599 if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
1600 s->opt[option].cap &= ~SANE_CAP_INACTIVE;
1601 *change = SANE_TRUE;
1602 }
1603 }
1604
1605 static void
deactivateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change)1606 deactivateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change)
1607 {
1608 if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) {
1609 s->opt[option].cap |= SANE_CAP_INACTIVE;
1610 *change = SANE_TRUE;
1611 }
1612 }
1613
1614 static void
setOptionState(Epson_Scanner *s, SANE_Bool state, SANE_Int option, SANE_Bool *change)1615 setOptionState(Epson_Scanner *s, SANE_Bool state, SANE_Int option,
1616 SANE_Bool *change)
1617 {
1618 if (state)
1619 activateOption(s, option, change);
1620 else
1621 deactivateOption(s, option, change);
1622 }
1623
1624 static SANE_Status
getvalue(SANE_Handle handle, SANE_Int option, void *value)1625 getvalue(SANE_Handle handle, SANE_Int option, void *value)
1626 {
1627 Epson_Scanner *s = (Epson_Scanner *) handle;
1628 SANE_Option_Descriptor *sopt = &(s->opt[option]);
1629 Option_Value *sval = &(s->val[option]);
1630
1631 DBG(17, "%s: option = %d\n", __func__, option);
1632
1633 switch (option) {
1634
1635 case OPT_GAMMA_VECTOR_R:
1636 case OPT_GAMMA_VECTOR_G:
1637 case OPT_GAMMA_VECTOR_B:
1638 case OPT_CCT_PROFILE:
1639 memcpy(value, sval->wa, sopt->size);
1640 break;
1641
1642 case OPT_NUM_OPTS:
1643 case OPT_RESOLUTION:
1644 case OPT_TL_X:
1645 case OPT_TL_Y:
1646 case OPT_BR_X:
1647 case OPT_BR_Y:
1648 case OPT_MIRROR:
1649 case OPT_AAS:
1650 case OPT_PREVIEW:
1651 case OPT_BRIGHTNESS:
1652 case OPT_SHARPNESS:
1653 case OPT_AUTO_EJECT:
1654 case OPT_THRESHOLD:
1655 case OPT_BIT_DEPTH:
1656 case OPT_WAIT_FOR_BUTTON:
1657 case OPT_AUTOFOCUS:
1658 case OPT_FOCUS_POS:
1659 *((SANE_Word *) value) = sval->w;
1660 break;
1661
1662 case OPT_MODE:
1663 case OPT_CCT_MODE:
1664 case OPT_ADF_MODE:
1665 case OPT_HALFTONE:
1666 case OPT_DROPOUT:
1667 case OPT_SOURCE:
1668 case OPT_FILM_TYPE:
1669 case OPT_GAMMA_CORRECTION:
1670 case OPT_COLOR_CORRECTION:
1671 case OPT_BAY:
1672 strcpy((char *) value, sopt->constraint.string_list[sval->w]);
1673 break;
1674
1675 default:
1676 return SANE_STATUS_INVAL;
1677 }
1678
1679 return SANE_STATUS_GOOD;
1680 }
1681
1682 /*
1683 * This routine handles common options between OPT_MODE and
1684 * OPT_HALFTONE. These options are TET (a HALFTONE mode), AAS
1685 * - auto area segmentation, and threshold. Apparently AAS
1686 * is some method to differentiate between text and photos.
1687 * Or something like that.
1688 *
1689 * AAS is available when the scan color depth is 1 and the
1690 * halftone method is not TET.
1691 *
1692 * Threshold is available when halftone is NONE, and depth is 1.
1693 */
1694 static void
handle_depth_halftone(Epson_Scanner *s, SANE_Bool *reload)1695 handle_depth_halftone(Epson_Scanner *s, SANE_Bool *reload)
1696 {
1697 int hti = s->val[OPT_HALFTONE].w;
1698 int mdi = s->val[OPT_MODE].w;
1699 SANE_Bool aas = SANE_FALSE;
1700 SANE_Bool thresh = SANE_FALSE;
1701
1702 /* this defaults to false */
1703 setOptionState(s, thresh, OPT_THRESHOLD, reload);
1704
1705 if (!s->hw->cmd->control_auto_area_segmentation)
1706 return;
1707
1708 if (mode_params[mdi].depth == 1) {
1709
1710 if (halftone_params[hti] != HALFTONE_TET)
1711 aas = SANE_TRUE;
1712
1713 if (halftone_params[hti] == HALFTONE_NONE)
1714 thresh = SANE_TRUE;
1715 }
1716 setOptionState(s, aas, OPT_AAS, reload);
1717 setOptionState(s, thresh, OPT_THRESHOLD, reload);
1718 }
1719
1720 /*
1721 * Handles setting the source (flatbed, transparency adapter (TPU),
1722 * or auto document feeder (ADF)).
1723 *
1724 * For newer scanners it also sets the focus according to the
1725 * glass / TPU settings.
1726 */
1727
1728 static void
change_source(Epson_Scanner *s, SANE_Int optindex, char *value)1729 change_source(Epson_Scanner *s, SANE_Int optindex, char *value)
1730 {
1731 int force_max = SANE_FALSE;
1732 SANE_Bool dummy;
1733
1734 DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex,
1735 value);
1736
1737 /* reset the scanner when we are changing the source setting -
1738 this is necessary for the Perfection 1650 */
1739 if (s->hw->need_reset_on_source_change)
1740 esci_reset(s);
1741
1742 if (s->val[OPT_SOURCE].w == optindex)
1743 return;
1744
1745 s->val[OPT_SOURCE].w = optindex;
1746
1747 if (s->val[OPT_TL_X].w == s->hw->x_range->min
1748 && s->val[OPT_TL_Y].w == s->hw->y_range->min
1749 && s->val[OPT_BR_X].w == s->hw->x_range->max
1750 && s->val[OPT_BR_Y].w == s->hw->y_range->max) {
1751 force_max = SANE_TRUE;
1752 }
1753
1754 if (strcmp(ADF_STR, value) == 0) {
1755 s->hw->x_range = &s->hw->adf_x_range;
1756 s->hw->y_range = &s->hw->adf_y_range;
1757 s->hw->use_extension = SANE_TRUE;
1758 /* disable film type option */
1759 deactivateOption(s, OPT_FILM_TYPE, &dummy);
1760 s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
1761 if (s->hw->duplex) {
1762 activateOption(s, OPT_ADF_MODE, &dummy);
1763 } else {
1764 deactivateOption(s, OPT_ADF_MODE, &dummy);
1765 s->val[OPT_ADF_MODE].w = 0;
1766 }
1767
1768 DBG(1, "adf activated (ext: %d, duplex: %d)\n",
1769 s->hw->use_extension,
1770 s->hw->duplex);
1771
1772 } else if (strcmp(TPU_STR, value) == 0 || strcmp(TPU_STR2, value) == 0) {
1773 if (strcmp(TPU_STR, value) == 0) {
1774 s->hw->x_range = &s->hw->tpu_x_range;
1775 s->hw->y_range = &s->hw->tpu_y_range;
1776 s->hw->TPU2 = SANE_FALSE;
1777 }
1778 if (strcmp(TPU_STR2, value) == 0) {
1779 s->hw->x_range = &s->hw->tpu2_x_range;
1780 s->hw->y_range = &s->hw->tpu2_y_range;
1781 s->hw->TPU2 = SANE_TRUE;
1782 }
1783 s->hw->use_extension = SANE_TRUE;
1784
1785 /* enable film type option only if the scanner supports it */
1786 if (s->hw->cmd->set_film_type != 0)
1787 activateOption(s, OPT_FILM_TYPE, &dummy);
1788 else
1789 deactivateOption(s, OPT_FILM_TYPE, &dummy);
1790
1791 /* enable focus position if the scanner supports it */
1792 if (s->hw->focusSupport)
1793 s->val[OPT_FOCUS_POS].w = FOCUS_ABOVE_25MM;
1794
1795 deactivateOption(s, OPT_ADF_MODE, &dummy);
1796 deactivateOption(s, OPT_EJECT, &dummy);
1797 deactivateOption(s, OPT_AUTO_EJECT, &dummy);
1798 } else {
1799 /* neither ADF nor TPU active */
1800 s->hw->x_range = &s->hw->fbf_x_range;
1801 s->hw->y_range = &s->hw->fbf_y_range;
1802 s->hw->use_extension = SANE_FALSE;
1803
1804 /* disable film type option */
1805 deactivateOption(s, OPT_FILM_TYPE, &dummy);
1806 s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
1807 deactivateOption(s, OPT_ADF_MODE, &dummy);
1808 }
1809
1810 /* special handling for FilmScan 200 */
1811 if (s->hw->cmd->level[0] == 'F')
1812 activateOption(s, OPT_FILM_TYPE, &dummy);
1813
1814 s->opt[OPT_BR_X].constraint.range = s->hw->x_range;
1815 s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
1816
1817 if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max)
1818 s->val[OPT_TL_X].w = s->hw->x_range->min;
1819
1820 if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max)
1821 s->val[OPT_TL_Y].w = s->hw->y_range->min;
1822
1823 if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max)
1824 s->val[OPT_BR_X].w = s->hw->x_range->max;
1825
1826 if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max)
1827 s->val[OPT_BR_Y].w = s->hw->y_range->max;
1828
1829 setOptionState(s, s->hw->ADF
1830 && s->hw->use_extension, OPT_AUTO_EJECT, &dummy);
1831 setOptionState(s, s->hw->ADF
1832 && s->hw->use_extension, OPT_EJECT, &dummy);
1833 }
1834
1835 static SANE_Status
setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)1836 setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
1837 {
1838 Epson_Scanner *s = (Epson_Scanner *) handle;
1839 SANE_Option_Descriptor *sopt = &(s->opt[option]);
1840 Option_Value *sval = &(s->val[option]);
1841
1842 SANE_Status status;
1843 const SANE_String_Const *optval = NULL;
1844 int optindex = 0;
1845 SANE_Bool reload = SANE_FALSE;
1846
1847 DBG(17, "%s: option = %d, value = %p\n", __func__, option, value);
1848
1849 status = sanei_constrain_value(sopt, value, info);
1850 if (status != SANE_STATUS_GOOD)
1851 return status;
1852
1853 if (info && value && (*info & SANE_INFO_INEXACT)
1854 && sopt->type == SANE_TYPE_INT)
1855 DBG(17, "%s: constrained val = %d\n", __func__,
1856 *(SANE_Word *) value);
1857
1858 if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) {
1859 optval = search_string_list(sopt->constraint.string_list,
1860 (char *) value);
1861 if (optval == NULL)
1862 return SANE_STATUS_INVAL;
1863 optindex = optval - sopt->constraint.string_list;
1864 }
1865
1866 switch (option) {
1867
1868 case OPT_GAMMA_VECTOR_R:
1869 case OPT_GAMMA_VECTOR_G:
1870 case OPT_GAMMA_VECTOR_B:
1871 case OPT_CCT_PROFILE:
1872 memcpy(sval->wa, value, sopt->size); /* Word arrays */
1873 break;
1874
1875 case OPT_CCT_MODE:
1876 case OPT_ADF_MODE:
1877 case OPT_DROPOUT:
1878 case OPT_FILM_TYPE:
1879 case OPT_BAY:
1880 sval->w = optindex; /* Simple lists */
1881 break;
1882
1883 case OPT_EJECT:
1884 /* XXX required? control_extension(s, 1); */
1885 esci_eject(s);
1886 break;
1887
1888 case OPT_RESOLUTION:
1889 sval->w = *((SANE_Word *) value);
1890 DBG(17, "setting resolution to %d\n", sval->w);
1891 reload = SANE_TRUE;
1892 break;
1893
1894 case OPT_BR_X:
1895 case OPT_BR_Y:
1896 if (SANE_UNFIX(*((SANE_Word *) value)) == 0) {
1897 DBG(17, "invalid br-x or br-y\n");
1898 return SANE_STATUS_INVAL;
1899 }
1900 // fall through
1901 case OPT_TL_X:
1902 case OPT_TL_Y:
1903 sval->w = *((SANE_Word *) value);
1904 DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w));
1905 if (NULL != info)
1906 *info |= SANE_INFO_RELOAD_PARAMS;
1907 break;
1908
1909 case OPT_SOURCE:
1910 change_source(s, optindex, (char *) value);
1911 reload = SANE_TRUE;
1912 break;
1913
1914 case OPT_MODE:
1915 {
1916 SANE_Bool isColor = mode_params[optindex].color;
1917
1918 sval->w = optindex;
1919
1920 DBG(17, "%s: setting mode to %d\n", __func__, optindex);
1921
1922 /* halftoning available only on bw scans */
1923 if (s->hw->cmd->set_halftoning != 0)
1924 setOptionState(s, mode_params[optindex].depth == 1,
1925 OPT_HALFTONE, &reload);
1926
1927 /* disable dropout on non-color scans */
1928 setOptionState(s, !isColor, OPT_DROPOUT, &reload);
1929
1930 if (s->hw->cmd->set_color_correction)
1931 setOptionState(s, isColor,
1932 OPT_COLOR_CORRECTION, &reload);
1933
1934 /* if binary, then disable the bit depth selection */
1935 if (optindex == 0) {
1936 DBG(17, "%s: disabling bit depth selection\n", __func__);
1937 s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
1938 } else {
1939 if (s->hw->depth_list[0] == 1) {
1940 DBG(17, "%s: only one depth is available\n", __func__);
1941 s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
1942 } else {
1943
1944 DBG(17, "%s: enabling bit depth selection\n", __func__);
1945
1946 s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE;
1947 s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth;
1948 }
1949 }
1950
1951 handle_depth_halftone(s, &reload);
1952 reload = SANE_TRUE;
1953
1954 break;
1955 }
1956
1957 case OPT_BIT_DEPTH:
1958 sval->w = *((SANE_Word *) value);
1959 mode_params[s->val[OPT_MODE].w].depth = sval->w;
1960 reload = SANE_TRUE;
1961 break;
1962
1963 case OPT_HALFTONE:
1964 sval->w = optindex;
1965 handle_depth_halftone(s, &reload);
1966 break;
1967
1968 case OPT_COLOR_CORRECTION:
1969 {
1970 sval->w = optindex;
1971 break;
1972 }
1973
1974 case OPT_GAMMA_CORRECTION:
1975 {
1976 SANE_Bool f = gamma_userdefined[optindex];
1977
1978 sval->w = optindex;
1979
1980 setOptionState(s, f, OPT_GAMMA_VECTOR_R, &reload);
1981 setOptionState(s, f, OPT_GAMMA_VECTOR_G, &reload);
1982 setOptionState(s, f, OPT_GAMMA_VECTOR_B, &reload);
1983 setOptionState(s, !f, OPT_BRIGHTNESS, &reload); /* Note... */
1984
1985 break;
1986 }
1987
1988 case OPT_AUTOFOCUS:
1989 sval->w = *((SANE_Word *) value);
1990 setOptionState(s, !sval->w, OPT_FOCUS_POS, &reload);
1991 break;
1992
1993 case OPT_MIRROR:
1994 case OPT_AAS:
1995 case OPT_PREVIEW: /* needed? */
1996 case OPT_BRIGHTNESS:
1997 case OPT_SHARPNESS:
1998 case OPT_AUTO_EJECT:
1999 case OPT_THRESHOLD:
2000 case OPT_WAIT_FOR_BUTTON:
2001 case OPT_FOCUS_POS:
2002 sval->w = *((SANE_Word *) value);
2003 break;
2004
2005 default:
2006 return SANE_STATUS_INVAL;
2007 }
2008
2009 if (reload && info != NULL)
2010 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2011
2012 DBG(17, "%s: end\n", __func__);
2013
2014 return SANE_STATUS_GOOD;
2015 }
2016
2017 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info)2018 sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
2019 void *value, SANE_Int *info)
2020 {
2021 DBG(17, "%s: action = %x, option = %d\n", __func__, action, option);
2022
2023 if (option < 0 || option >= NUM_OPTIONS)
2024 return SANE_STATUS_INVAL;
2025
2026 if (info != NULL)
2027 *info = 0;
2028
2029 switch (action) {
2030 case SANE_ACTION_GET_VALUE:
2031 return getvalue(handle, option, value);
2032
2033 case SANE_ACTION_SET_VALUE:
2034 return setvalue(handle, option, value, info);
2035
2036 default:
2037 return SANE_STATUS_INVAL;
2038 }
2039
2040 return SANE_STATUS_INVAL;
2041 }
2042
2043 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)2044 sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)
2045 {
2046 Epson_Scanner *s = (Epson_Scanner *) handle;
2047
2048 DBG(5, "%s\n", __func__);
2049
2050 if (params == NULL)
2051 DBG(1, "%s: params is NULL\n", __func__);
2052
2053 /*
2054 * If sane_start was already called, then just retrieve the parameters
2055 * from the scanner data structure
2056 */
2057
2058 if (!s->eof && s->ptr != NULL) {
2059 DBG(5, "scan in progress, returning saved params structure\n");
2060 } else {
2061 /* otherwise initialize the params structure and gather the data */
2062 e2_init_parameters(s);
2063 }
2064
2065 if (params != NULL)
2066 *params = s->params;
2067
2068 print_params(s->params);
2069
2070 return SANE_STATUS_GOOD;
2071 }
2072
e2_load_cct_profile(struct Epson_Scanner *s, unsigned int index)2073 static void e2_load_cct_profile(struct Epson_Scanner *s, unsigned int index)
2074 {
2075 s->cct_table[0] = SANE_FIX(s->hw->cct_profile->cct[index][0]);
2076 s->cct_table[1] = SANE_FIX(s->hw->cct_profile->cct[index][1]);
2077 s->cct_table[2] = SANE_FIX(s->hw->cct_profile->cct[index][2]);
2078 s->cct_table[3] = SANE_FIX(s->hw->cct_profile->cct[index][3]);
2079 s->cct_table[4] = SANE_FIX(s->hw->cct_profile->cct[index][4]);
2080 s->cct_table[5] = SANE_FIX(s->hw->cct_profile->cct[index][5]);
2081 s->cct_table[6] = SANE_FIX(s->hw->cct_profile->cct[index][6]);
2082 s->cct_table[7] = SANE_FIX(s->hw->cct_profile->cct[index][7]);
2083 s->cct_table[8] = SANE_FIX(s->hw->cct_profile->cct[index][8]);
2084 }
2085
2086 /*
2087 * This function is part of the SANE API and gets called from the front end to
2088 * start the scan process.
2089 */
2090
2091 SANE_Status
sane_start(SANE_Handle handle)2092 sane_start(SANE_Handle handle)
2093 {
2094 Epson_Scanner *s = (Epson_Scanner *) handle;
2095 Epson_Device *dev = s->hw;
2096 SANE_Status status;
2097
2098 DBG(5, "* %s\n", __func__);
2099
2100 s->eof = SANE_FALSE;
2101 s->canceling = SANE_FALSE;
2102
2103 /* check if we just have finished working with the ADF */
2104 status = e2_check_adf(s);
2105 if (status != SANE_STATUS_GOOD)
2106 return status;
2107
2108 /* calc scanning parameters */
2109 status = e2_init_parameters(s);
2110 if (status != SANE_STATUS_GOOD)
2111 return status;
2112
2113 print_params(s->params);
2114
2115 /* enable infrared */
2116 if (s->val[OPT_MODE].w == MODE_INFRARED)
2117 esci_enable_infrared(handle);
2118
2119 /* ESC , bay */
2120 if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BAY].cap)) {
2121 status = esci_set_bay(s, s->val[OPT_BAY].w);
2122 if (status != SANE_STATUS_GOOD)
2123 return status;
2124 }
2125
2126 /* set scanning parameters */
2127 if (dev->extended_commands)
2128 status = e2_set_extended_scanning_parameters(s);
2129 else
2130 status = e2_set_scanning_parameters(s);
2131
2132 if (status != SANE_STATUS_GOOD)
2133 return status;
2134
2135 /*
2136 * set focus after we set scanning parameters because the scanner will
2137 * use the middle of the scanning area for autofocus. If we want to
2138 * support a defined x,y position for autofocus, we'd need to send
2139 * specific scanning paramters just for autofocus.
2140 */
2141 if (s->hw->focusSupport == SANE_TRUE) {
2142 if (s->val[OPT_AUTOFOCUS].w) {
2143 DBG(1, "setting autofocus\n");
2144 status = esci_set_focus_position(s, 0xff);
2145 } else {
2146 DBG(1, "setting focus to %u\n", s->val[OPT_FOCUS_POS].w);
2147 status = esci_set_focus_position(s, s->val[OPT_FOCUS_POS].w);
2148 }
2149
2150 if (status != SANE_STATUS_GOOD) {
2151 DBG(1, "setting focus failed\n");
2152 return status;
2153 }
2154 }
2155
2156 /* ESC z, user defined gamma table */
2157 if (dev->cmd->set_gamma_table
2158 && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w]) {
2159 status = esci_set_gamma_table(s);
2160 if (status != SANE_STATUS_GOOD)
2161 return status;
2162 }
2163
2164
2165 if (s->val[OPT_COLOR_CORRECTION].w == CORR_AUTO) { /* Automatic */
2166
2167 DBG(1, "using built in CCT profile\n");
2168
2169 if (dev->model_id == 0)
2170 DBG(1, " specific profile not available, using default\n");
2171
2172
2173 if (0) { /* XXX TPU */
2174
2175 /* XXX check this */
2176 if (s->val[OPT_FILM_TYPE].w == 0)
2177 e2_load_cct_profile(s, CCTP_COLORPOS);
2178 else
2179 e2_load_cct_profile(s, CCTP_COLORNEG);
2180
2181 } else {
2182 e2_load_cct_profile(s, CCTP_REFLECTIVE);
2183 }
2184 }
2185
2186 /* ESC m, user defined color correction */
2187 if (s->hw->cmd->set_color_correction_coefficients
2188 && correction_userdefined[s->val[OPT_COLOR_CORRECTION].w]) {
2189
2190 status = esci_set_color_correction_coefficients(s,
2191 s->cct_table);
2192 if (status != SANE_STATUS_GOOD)
2193 return status;
2194 }
2195
2196 /* check if we just have finished working with the ADF.
2197 * this seems to work only after the scanner has been
2198 * set up with scanning parameters
2199 */
2200 status = e2_check_adf(s);
2201 if (status != SANE_STATUS_GOOD)
2202 return status;
2203
2204 /*
2205 * If WAIT_FOR_BUTTON is active, then do just that:
2206 * Wait until the button is pressed. If the button was already
2207 * pressed, then we will get the button pressed event right away.
2208 */
2209 if (s->val[OPT_WAIT_FOR_BUTTON].w == SANE_TRUE)
2210 e2_wait_button(s);
2211
2212 /* for debug, request command parameter */
2213 /* if (DBG_LEVEL) {
2214 unsigned char buf[45];
2215 request_command_parameter(s, buf);
2216 }
2217 */
2218 /* set the retry count to 0 */
2219 s->retry_count = 0;
2220
2221 /* allocate buffers for color shuffling */
2222 if (dev->color_shuffle == SANE_TRUE) {
2223 int i;
2224 /* initialize the line buffers */
2225 for (i = 0; i < s->line_distance * 2 + 1; i++) {
2226
2227 if (s->line_buffer[i] != NULL)
2228 free(s->line_buffer[i]);
2229
2230 s->line_buffer[i] = malloc(s->params.bytes_per_line);
2231 if (s->line_buffer[i] == NULL) {
2232 DBG(1, "out of memory (line %d)\n", __LINE__);
2233 return SANE_STATUS_NO_MEM;
2234 }
2235 }
2236 }
2237
2238 /* prepare buffer here so that a memory allocation failure
2239 * will leave the scanner in a sane state.
2240 * the buffer will have to hold the image data plus
2241 * an error code in the extended handshaking mode.
2242 */
2243 s->buf = realloc(s->buf, (s->lcount * s->params.bytes_per_line) + 1);
2244 if (s->buf == NULL)
2245 return SANE_STATUS_NO_MEM;
2246
2247 s->ptr = s->end = s->buf;
2248
2249 /* feed the first sheet in the ADF */
2250 if (dev->ADF && dev->use_extension && dev->cmd->feed) {
2251 status = esci_feed(s);
2252 if (status != SANE_STATUS_GOOD)
2253 return status;
2254 }
2255
2256 /* this seems to work only for some devices */
2257 status = e2_wait_warm_up(s);
2258 if (status != SANE_STATUS_GOOD)
2259 return status;
2260
2261 if (s->hw->focusSupport == SANE_TRUE && s->val[OPT_AUTOFOCUS].w) {
2262 status = esci_request_focus_position(s, &s->currentFocusPosition);
2263 if (status == SANE_STATUS_GOOD)
2264 s->val[OPT_FOCUS_POS].w = s->currentFocusPosition;
2265 }
2266
2267 /* start scanning */
2268 DBG(1, "%s: scanning...\n", __func__);
2269
2270 if (dev->extended_commands) {
2271 status = e2_start_ext_scan(s);
2272
2273 /* sometimes the scanner gives an io error when
2274 * it's warming up.
2275 */
2276 if (status == SANE_STATUS_IO_ERROR) {
2277 status = e2_wait_warm_up(s);
2278 if (status == SANE_STATUS_GOOD)
2279 status = e2_start_ext_scan(s);
2280 }
2281 } else
2282 status = e2_start_std_scan(s);
2283
2284 if (status != SANE_STATUS_GOOD) {
2285 DBG(1, "%s: start failed: %s\n", __func__,
2286 sane_strstatus(status));
2287
2288 return status;
2289 }
2290
2291 /* this is a kind of read request */
2292 if (dev->connection == SANE_EPSON_NET) {
2293 sanei_epson_net_write(s, 0x2000, NULL, 0,
2294 s->ext_block_len + 1, &status);
2295 }
2296
2297 return status;
2298 }
2299
2300 /* this moves data from our buffers to SANE */
2301
2302 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length)2303 sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
2304 SANE_Int *length)
2305 {
2306 SANE_Status status;
2307 Epson_Scanner *s = (Epson_Scanner *) handle;
2308
2309 DBG(18, "* %s: eof: %d, canceling: %d\n",
2310 __func__, s->eof, s->canceling);
2311
2312 /* sane_read called before sane_start? */
2313 if (s->buf == NULL) {
2314 DBG(1, "%s: buffer is NULL", __func__);
2315 return SANE_STATUS_INVAL;
2316 }
2317
2318 *length = 0;
2319
2320 if (s->hw->extended_commands)
2321 status = e2_ext_read(s);
2322 else
2323 status = e2_block_read(s);
2324
2325 /* The scanning operation might be canceled by the scanner itself
2326 * or the fronted program
2327 */
2328 if (status == SANE_STATUS_CANCELLED || s->canceling) {
2329 e2_scan_finish(s);
2330 return SANE_STATUS_CANCELLED;
2331 }
2332
2333 /* XXX if FS G and STATUS_IOERR, use e2_check_extended_status */
2334
2335 DBG(18, "moving data %p %p, %d (%d lines)\n",
2336 (void *) s->ptr, (void *) s->end,
2337 max_length, max_length / s->params.bytes_per_line);
2338
2339 e2_copy_image_data(s, data, max_length, length);
2340
2341 DBG(18, "%d lines read, eof: %d, canceling: %d, status: %d\n",
2342 *length / s->params.bytes_per_line,
2343 s->canceling, s->eof, status);
2344
2345 /* continue reading if appropriate */
2346 if (status == SANE_STATUS_GOOD)
2347 return status;
2348
2349 e2_scan_finish(s);
2350
2351 return status;
2352 }
2353
2354 /*
2355 * void sane_cancel(SANE_Handle handle)
2356 *
2357 * Set the cancel flag to true. The next time the backend requests data
2358 * from the scanner the CAN message will be sent.
2359 */
2360
2361 void
sane_cancel(SANE_Handle handle)2362 sane_cancel(SANE_Handle handle)
2363 {
2364 Epson_Scanner *s = (Epson_Scanner *) handle;
2365
2366 DBG(1, "* %s\n", __func__);
2367
2368 s->canceling = SANE_TRUE;
2369 }
2370
2371 /*
2372 * SANE_Status sane_set_io_mode()
2373 *
2374 * not supported - for asynchronous I/O
2375 */
2376
2377 SANE_Status
sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking)2378 sane_set_io_mode(SANE_Handle __sane_unused__ handle,
2379 SANE_Bool __sane_unused__ non_blocking)
2380 {
2381 return SANE_STATUS_UNSUPPORTED;
2382 }
2383
2384 /*
2385 * SANE_Status sane_get_select_fd()
2386 *
2387 * not supported - for asynchronous I/O
2388 */
2389
2390 SANE_Status
sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd)2391 sane_get_select_fd(SANE_Handle __sane_unused__ handle,
2392 SANE_Int __sane_unused__ *fd)
2393 {
2394 return SANE_STATUS_UNSUPPORTED;
2395 }
2396