1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1997 David Mosberger-Tang
3 This file is part of the SANE package.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18 As a special exception, the authors of SANE give permission for
19 additional uses of the libraries contained in this release of SANE.
20
21 The exception is that, if you link a SANE library with other files
22 to produce an executable, this does not by itself cause the
23 resulting executable to be covered by the GNU General Public
24 License. Your use of that executable is in no way restricted on
25 account of linking the SANE library code into it.
26
27 This exception does not, however, invalidate any other reasons why
28 the executable file might be covered by the GNU General Public
29 License.
30
31 If you submit changes to SANE to the maintainers to be included in
32 a subsequent release, you agree by submitting the changes that
33 those changes may be distributed with this exception intact.
34
35 If you write modifications of your own for SANE, it is your choice
36 whether to permit this exception to apply to your modifications.
37 If you do not wish that, delete this exception notice.
38
39 This file implements a SANE backend for the Artec/Ultima scanners.
40
41 Copyright (C) 1998-2000 Chris Pinkham
42 Released under the terms of the GPL.
43 *NO WARRANTY*
44
45 Portions contributed by:
46 David Leadbetter - A6000C (3-pass)
47 Dick Bruijn - AT12
48
49 *********************************************************************
50 For feedback/information:
51
52 cpinkham@corp.infi.net
53 http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html
54 *********************************************************************
55 */
56
57 #include "../include/sane/config.h"
58
59 #include <ctype.h>
60 #include <limits.h>
61 #include <stdlib.h>
62 #include <stdarg.h>
63 #include <string.h>
64 #include <unistd.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <fcntl.h>
68
69 #include "../include/_stdint.h"
70
71 #include "../include/sane/sane.h"
72 #include "../include/sane/saneopts.h"
73 #include "../include/sane/sanei_scsi.h"
74 #include "../include/sane/sanei_backend.h"
75 #include "../include/sane/sanei_config.h"
76
77 #include <artec.h>
78
79 #define BACKEND_NAME artec
80
81 #define ARTEC_MAJOR 0
82 #define ARTEC_MINOR 5
83 #define ARTEC_SUB 16
84 #define ARTEC_LAST_MOD "05/26/2001 17:28 EST"
85
86
87 #ifndef PATH_MAX
88 #define PATH_MAX 1024
89 #endif
90
91 #define ARTEC_CONFIG_FILE "artec.conf"
92 #define ARTEC_MAX_READ_SIZE 32768
93
94 static int num_devices;
95 static const SANE_Device **devlist = 0;
96 static ARTEC_Device *first_dev;
97 static ARTEC_Scanner *first_handle;
98
99 static const SANE_String_Const mode_list[] =
100 {
101 SANE_VALUE_SCAN_MODE_LINEART,
102 SANE_VALUE_SCAN_MODE_HALFTONE,
103 SANE_VALUE_SCAN_MODE_GRAY,
104 SANE_VALUE_SCAN_MODE_COLOR,
105 0
106 };
107
108 static const SANE_String_Const filter_type_list[] =
109 {
110 "Mono", "Red", "Green", "Blue",
111 0
112 };
113
114 static const SANE_String_Const halftone_pattern_list[] =
115 {
116 "User defined (unsupported)", "4x4 Spiral", "4x4 Bayer", "8x8 Spiral",
117 "8x8 Bayer",
118 0
119 };
120
121 static const SANE_Range u8_range =
122 {
123 0, /* minimum */
124 255, /* maximum */
125 0 /* quantization */
126 };
127
128 #define INQ_LEN 0x60
129 static const uint8_t inquiry[] =
130 {
131 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00
132 };
133
134 static const uint8_t test_unit_ready[] =
135 {
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
137 };
138
139 static struct
140 {
141 SANE_String model; /* product model */
142 SANE_String type; /* type of scanner */
143 double width; /* width in inches */
144 double height; /* height in inches */
145 SANE_Word adc_bits; /* Analog-to-Digital Converter Bits */
146 SANE_Word setwindow_cmd_size; /* Set-Window command size */
147 SANE_Word max_read_size; /* Max Read size in bytes */
148 long flags; /* flags */
149 SANE_String horz_resolution_str; /* Horizontal resolution list */
150 SANE_String vert_resolution_str; /* Vertical resolution list */
151 }
152 cap_data[] =
153 {
154 {
155 "AT3", "flatbed",
156 8.3, 11, 8, 55, 32768,
157 ARTEC_FLAG_CALIBRATE_RGB |
158 ARTEC_FLAG_RGB_LINE_OFFSET |
159 ARTEC_FLAG_RGB_CHAR_SHIFT |
160 ARTEC_FLAG_OPT_CONTRAST |
161 ARTEC_FLAG_GAMMA_SINGLE |
162 ARTEC_FLAG_SEPARATE_RES |
163 ARTEC_FLAG_SENSE_HANDLER |
164 ARTEC_FLAG_SENSE_BYTE_19 |
165 ARTEC_FLAG_ADF |
166 ARTEC_FLAG_HALFTONE_PATTERN |
167 ARTEC_FLAG_MBPP_NEGATIVE |
168 ARTEC_FLAG_ONE_PASS_SCANNER,
169 "50,100,200,300", "50,100,200,300,600"
170 }
171 ,
172 {
173 "A6000C", "flatbed",
174 8.3, 14, 8, 55, 8192,
175 /* some have reported that Calibration does not work the same as AT3 & A6000C+
176 ARTEC_FLAG_CALIBRATE_RGB |
177 */
178 ARTEC_FLAG_OPT_CONTRAST |
179 ARTEC_FLAG_OPT_BRIGHTNESS |
180 ARTEC_FLAG_SEPARATE_RES |
181 ARTEC_FLAG_SENSE_HANDLER |
182 ARTEC_FLAG_ADF |
183 ARTEC_FLAG_HALFTONE_PATTERN,
184 "50,100,200,300", "50,100,200,300,600"
185 }
186 ,
187 {
188 "A6000C PLUS", "flatbed",
189 8.3, 14, 8, 55, 8192,
190 ARTEC_FLAG_CALIBRATE_RGB |
191 ARTEC_FLAG_RGB_LINE_OFFSET |
192 ARTEC_FLAG_RGB_CHAR_SHIFT |
193 ARTEC_FLAG_OPT_CONTRAST |
194 ARTEC_FLAG_GAMMA_SINGLE |
195 ARTEC_FLAG_SEPARATE_RES |
196 ARTEC_FLAG_SENSE_HANDLER |
197 ARTEC_FLAG_SENSE_BYTE_19 |
198 ARTEC_FLAG_ADF |
199 ARTEC_FLAG_HALFTONE_PATTERN |
200 ARTEC_FLAG_MBPP_NEGATIVE |
201 ARTEC_FLAG_ONE_PASS_SCANNER,
202 "50,100,200,300", "50,100,200,300,600"
203 }
204 ,
205 {
206 "AT6", "flatbed",
207 8.3, 11, 10, 55, 32768,
208 ARTEC_FLAG_CALIBRATE_RGB |
209 ARTEC_FLAG_RGB_LINE_OFFSET |
210 ARTEC_FLAG_RGB_CHAR_SHIFT |
211 ARTEC_FLAG_OPT_CONTRAST |
212 /* gamma not working totally correct yet.
213 ARTEC_FLAG_GAMMA_SINGLE |
214 */
215 ARTEC_FLAG_SEPARATE_RES |
216 ARTEC_FLAG_SENSE_HANDLER |
217 ARTEC_FLAG_ADF |
218 ARTEC_FLAG_HALFTONE_PATTERN |
219 ARTEC_FLAG_MBPP_NEGATIVE |
220 ARTEC_FLAG_ONE_PASS_SCANNER,
221 "50,100,200,300", "50,100,200,300,600"
222 }
223 ,
224 {
225 "AT12", "flatbed",
226 8.5, 11, 12, 67, 32768,
227 /* calibration works slower so disabled
228 ARTEC_CALIBRATE_DARK_WHITE |
229 */
230 /* gamma not working totally correct yet.
231 ARTEC_FLAG_GAMMA |
232 */
233 ARTEC_FLAG_OPT_CONTRAST |
234 ARTEC_FLAG_SEPARATE_RES |
235 ARTEC_FLAG_SENSE_HANDLER |
236 ARTEC_FLAG_SENSE_ENH_18 |
237 ARTEC_FLAG_SENSE_BYTE_22 |
238 ARTEC_FLAG_SC_BUFFERS_LINES |
239 ARTEC_FLAG_SC_HANDLES_OFFSET |
240 ARTEC_FLAG_PIXEL_AVERAGING |
241 ARTEC_FLAG_ENHANCE_LINE_EDGE |
242 ARTEC_FLAG_ADF |
243 ARTEC_FLAG_HALFTONE_PATTERN |
244 ARTEC_FLAG_MBPP_NEGATIVE |
245 ARTEC_FLAG_ONE_PASS_SCANNER,
246 "25,50,100,200,300,400,500,600",
247 "25,50,100,200,300,400,500,600,700,800,900,1000,1100,1200"
248 }
249 ,
250 {
251 "AM12S", "flatbed",
252 8.26, 11.7, 12, 67, ARTEC_MAX_READ_SIZE,
253 /* calibration works slower so disabled
254 ARTEC_CALIBRATE_DARK_WHITE |
255 */
256 /* gamma not working totally correct yet.
257 ARTEC_FLAG_GAMMA |
258 */
259 ARTEC_FLAG_RGB_LINE_OFFSET |
260 ARTEC_FLAG_SEPARATE_RES |
261 ARTEC_FLAG_IMAGE_REV_LR |
262 ARTEC_FLAG_REVERSE_WINDOW |
263 ARTEC_FLAG_SENSE_HANDLER |
264 ARTEC_FLAG_SENSE_ENH_18 |
265 ARTEC_FLAG_MBPP_NEGATIVE |
266 ARTEC_FLAG_ONE_PASS_SCANNER,
267 "50,100,300,600",
268 "50,100,300,600,1200"
269 }
270 ,
271 };
272
273 /* store vendor and model if hardcoded in artec.conf */
274 static char artec_vendor[9] = "";
275 static char artec_model[17] = "";
276
277 /* file descriptor for debug data output */
278 static int debug_fd = -1;
279
artec_skip_whitespace(char *str)280 static char *artec_skip_whitespace (char *str)
281 {
282 while (isspace (*str))
283 ++str;
284 return str;
285 }
286
287 static SANE_Status
artec_str_list_to_word_list(SANE_Word ** word_list_ptr, SANE_String str)288 artec_str_list_to_word_list (SANE_Word ** word_list_ptr, SANE_String str)
289 {
290 SANE_Word *word_list;
291 char *start;
292 char *end;
293 char temp_str[1024];
294 int comma_count = 1;
295
296 if ((str == NULL) ||
297 (strlen (str) == 0))
298 {
299 /* alloc space for word which stores length (0 in this case) */
300 word_list = (SANE_Word *) malloc (sizeof (SANE_Word));
301 if (word_list == NULL)
302 return (SANE_STATUS_NO_MEM);
303
304 word_list[0] = 0;
305 *word_list_ptr = word_list;
306 return (SANE_STATUS_GOOD);
307 }
308
309 /* make temp copy of input string (only hold 1024 for now) */
310 strncpy (temp_str, str, 1023);
311 temp_str[1023] = '\0';
312
313 end = strchr (temp_str, ',');
314 while (end != NULL)
315 {
316 comma_count++;
317 start = end + 1;
318 end = strchr (start, ',');
319 }
320
321 word_list = (SANE_Word *) calloc (comma_count + 1,
322 sizeof (SANE_Word));
323
324 if (word_list == NULL)
325 return (SANE_STATUS_NO_MEM);
326
327 word_list[0] = comma_count;
328
329 comma_count = 1;
330 start = temp_str;
331 end = strchr (temp_str, ',');
332 while (end != NULL)
333 {
334 *end = '\0';
335 word_list[comma_count] = atol (start);
336
337 start = end + 1;
338 comma_count++;
339 end = strchr (start, ',');
340 }
341
342 word_list[comma_count] = atol (start);
343
344 *word_list_ptr = word_list;
345 return (SANE_STATUS_GOOD);
346 }
347
348 static size_t
artec_get_str_index(const SANE_String_Const strings[], char *str)349 artec_get_str_index (const SANE_String_Const strings[], char *str)
350 {
351 size_t index;
352
353 index = 0;
354 while ((strings[index]) && strcmp (strings[index], str))
355 {
356 index++;
357 }
358
359 if (!strings[index])
360 {
361 index = 0;
362 }
363
364 return (index);
365 }
366
367 static size_t
max_string_size(const SANE_String_Const strings[])368 max_string_size (const SANE_String_Const strings[])
369 {
370 size_t size, max_size = 0;
371 int i;
372
373 for (i = 0; strings[i]; ++i)
374 {
375 size = strlen (strings[i]) + 1;
376 if (size > max_size)
377 max_size = size;
378 }
379
380 return (max_size);
381 }
382
383 /* DB added a sense handler */
384 /* last argument is expected to be a pointer to a Artec_Scanner structure */
385 static SANE_Status
sense_handler(int fd, u_char * sense, void *arg)386 sense_handler (int fd, u_char * sense, void *arg)
387 {
388 ARTEC_Scanner *s = (ARTEC_Scanner *)arg;
389 int err;
390
391 err = 0;
392
393 DBG(2, "sense fd: %d, data: %02x %02x %02x %02x %02x %02x %02x %02x "
394 "%02x %02x %02x %02x %02x %02x %02x %02x\n", fd,
395 sense[0], sense[1], sense[2], sense[3],
396 sense[4], sense[5], sense[6], sense[7],
397 sense[8], sense[9], sense[10], sense[11],
398 sense[12], sense[13], sense[14], sense[15]);
399
400 /* byte 18 info pertaining to ADF */
401 if ((s) && (s->hw->flags & ARTEC_FLAG_ADF))
402 {
403 if (sense[18] & 0x01)
404 {
405 DBG (2, "sense: ADF PAPER JAM\n");
406 err++;
407 }
408 if (sense[18] & 0x02)
409 {
410 DBG (2, "sense: ADF NO DOCUMENT IN BIN\n");
411 err++;
412 }
413 if (sense[18] & 0x04)
414 {
415 DBG (2, "sense: ADF SWITCH COVER OPEN\n");
416 err++;
417 }
418 /* DB : next is, i think no failure, so no incrementing s */
419 if (sense[18] & 0x08)
420 {
421 DBG (2, "sense: ADF SET CORRECTLY ON TARGET\n");
422 }
423 /* The following only for AT12, its reserved (zero?) on other models, */
424 if (sense[18] & 0x10)
425 {
426 DBG (2, "sense: ADF LENGTH TOO SHORT\n");
427 err++;
428 }
429 }
430
431 /* enhanced byte 18 sense data */
432 if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_ENH_18))
433 {
434 if (sense[18] & 0x20)
435 {
436 DBG (2, "sense: LAMP FAIL : NOT WARM \n");
437 err++;
438 }
439 if (sense[18] & 0x40)
440 {
441 DBG (2, "sense: NOT READY STATE\n");
442 err++;
443 }
444 }
445
446 if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_19))
447 {
448 if (sense[19] & 0x01)
449 {
450 DBG (2, "sense: 8031 program ROM checksum Error\n");
451 err++;
452 }
453 if (sense[19] & 0x02)
454 {
455 DBG (2, "sense: 8031 data RAM R/W Error\n");
456 err++;
457 }
458 if (sense[19] & 0x04)
459 {
460 DBG (2, "sense: Shadow Correction RAM R/W Error\n");
461 err++;
462 }
463 if (sense[19] & 0x08)
464 {
465 DBG (2, "sense: Line RAM R/W Error\n");
466 err++;
467 }
468 if (sense[19] & 0x10)
469 {
470 /* docs say "reserved to '0'" */
471 DBG (2, "sense: CCD control circuit Error\n");
472 err++;
473 }
474 if (sense[19] & 0x20)
475 {
476 DBG (2, "sense: Motor End Switch Error\n");
477 err++;
478 }
479 if (sense[19] & 0x40)
480 {
481 /* docs say "reserved to '0'" */
482 DBG (2, "sense: Lamp Error\n");
483 err++;
484 }
485 if (sense[19] & 0x80)
486 {
487 DBG (2, "sense: Optical Calibration/Shading Error\n");
488 err++;
489 }
490 }
491
492 /* These are the self test results for tests 0-15 */
493 if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_22))
494 {
495 if (sense[22] & 0x01)
496 {
497 DBG (2, "sense: 8031 Internal Memory R/W Error\n");
498 err++;
499 }
500 if (sense[22] & 0x02)
501 {
502 DBG (2, "sense: EEPROM test pattern R/W Error\n");
503 err++;
504 }
505 if (sense[22] & 0x04)
506 {
507 DBG (2, "sense: ASIC Test Error\n");
508 err++;
509 }
510 if (sense[22] & 0x08)
511 {
512 DBG (2, "sense: Line RAM R/W Error\n");
513 err++;
514 }
515 if (sense[22] & 0x10)
516 {
517 DBG (2, "sense: PSRAM R/W Test Error\n");
518 err++;
519 }
520 if (sense[22] & 0x20)
521 {
522 DBG (2, "sense: Positioning Error\n");
523 err++;
524 }
525 if (sense[22] & 0x40)
526 {
527 DBG (2, "sense: Test 6 Error\n");
528 err++;
529 }
530 if (sense[22] & 0x80)
531 {
532 DBG (2, "sense: Test 7 Error\n");
533 err++;
534 }
535 if (sense[23] & 0x01)
536 {
537 DBG (2, "sense: Test 8 Error\n");
538 err++;
539 }
540 if (sense[23] & 0x02)
541 {
542 DBG (2, "sense: Test 9 Error\n");
543 err++;
544 }
545 if (sense[23] & 0x04)
546 {
547 DBG (2, "sense: Test 10 Error\n");
548 err++;
549 }
550 if (sense[23] & 0x08)
551 {
552 DBG (2, "sense: Test 11 Error\n");
553 err++;
554 }
555 if (sense[23] & 0x10)
556 {
557 DBG (2, "sense: Test 12 Error\n");
558 err++;
559 }
560 if (sense[23] & 0x20)
561 {
562 DBG (2, "sense: Test 13 Error\n");
563 err++;
564 }
565 if (sense[23] & 0x40)
566 {
567 DBG (2, "sense: Test 14 Error\n");
568 err++;
569 }
570 if (sense[23] & 0x80)
571 {
572 DBG (2, "sense: Test 15 Error\n");
573 err++;
574 }
575 }
576
577 if (err)
578 return SANE_STATUS_IO_ERROR;
579
580 switch (sense[0])
581 {
582 case 0x70: /* ALWAYS */
583 switch (sense[2])
584 {
585 case 0x00:
586 DBG (2, "sense: Successful command\n");
587 return SANE_STATUS_GOOD;
588 case 0x02:
589 DBG (2, "sense: Not Ready, target can not be accessed\n");
590 return SANE_STATUS_IO_ERROR;
591 case 0x03:
592 DBG (2, "sense: Medium Error, paper jam or misfeed during ADF\n");
593 return SANE_STATUS_IO_ERROR;
594 case 0x04:
595 DBG (2, "sense: Hardware Error, non-recoverable\n");
596 return SANE_STATUS_IO_ERROR;
597 case 0x05:
598 DBG (2, "sense: Illegal Request, bad parameter in command block\n");
599 return SANE_STATUS_IO_ERROR;
600 case 0x06:
601 DBG (2, "sense: Unit Attention\n");
602 return SANE_STATUS_GOOD;
603 default:
604 DBG (2, "sense: SENSE KEY UNKNOWN (%02x)\n", sense[2]);
605 return SANE_STATUS_IO_ERROR;
606 }
607 default:
608 DBG (2, "sense: Unknown Error Code Qualifier (%02x)\n", sense[0]);
609 return SANE_STATUS_IO_ERROR;
610 }
611
612 DBG (2, "sense: Should not come here!\n");
613 return SANE_STATUS_IO_ERROR;
614 }
615
616
617 /* DB added a wait routine for the scanner to come ready */
618 static SANE_Status
wait_ready(int fd)619 wait_ready (int fd)
620 {
621 SANE_Status status;
622 int retry = 30; /* make this tuneable? */
623
624 DBG (7, "wait_ready()\n");
625 while (retry-- > 0)
626 {
627 status = sanei_scsi_cmd (fd, test_unit_ready,
628 sizeof (test_unit_ready), 0, 0);
629 if (status == SANE_STATUS_GOOD)
630 return status;
631
632 if (status == SANE_STATUS_DEVICE_BUSY)
633 {
634 sleep (1);
635 continue;
636 }
637
638 /* status != GOOD && != BUSY */
639 DBG (9, "wait_ready: '%s'\n", sane_strstatus (status));
640 return status;
641 }
642
643 /* BUSY after n retries */
644 DBG (9, "wait_ready: '%s'\n", sane_strstatus (status));
645 return status;
646 }
647
648 /* DB added a abort routine, executed via mode select */
649 static SANE_Status
abort_scan(SANE_Handle handle)650 abort_scan (SANE_Handle handle)
651 {
652 ARTEC_Scanner *s = handle;
653 uint8_t *data, comm[22];
654
655 DBG (7, "abort_scan()\n");
656 memset (comm, 0, sizeof (comm));
657
658 comm[0] = 0x15;
659 comm[1] = 0x10;
660 comm[2] = 0x00;
661 comm[3] = 0x00;
662 comm[4] = 0x10;
663 comm[5] = 0x00;
664
665 data = comm + 6;
666 data[0] = 0x00; /* mode data length */
667 data[1] = 0x00; /* medium type */
668 data[2] = 0x00; /* device specific parameter */
669 data[3] = 0x00; /* block descriptor length */
670
671 data = comm + 10;
672 data[0] = 0x00; /* control page parameters */
673 data[1] = 0x0a; /* parameter length */
674 data[2] = 0x02 | ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) |
675 ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01);
676 data[3] = 0x00; /* reserved */
677 data[4] = 0x00; /* reserved */
678
679 DBG (9, "abort: sending abort command\n");
680 sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0);
681
682 DBG (9, "abort: wait for scanner to come ready...\n");
683 wait_ready (s->fd);
684
685 DBG (9, "abort: resetting abort status\n");
686 data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) |
687 ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01);
688 sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0);
689
690 DBG (9, "abort: wait for scanner to come ready...\n");
691 return wait_ready (s->fd);
692 }
693
694 /* DAL - mode_select: used for transparency and ADF scanning */
695 /* Based on abort_scan */
696 static SANE_Status
artec_mode_select(SANE_Handle handle)697 artec_mode_select (SANE_Handle handle)
698 {
699 ARTEC_Scanner *s = handle;
700 uint8_t *data, comm[22];
701
702 DBG (7, "artec_mode_select()\n");
703 memset (comm, 0, sizeof (comm));
704
705 comm[0] = 0x15;
706 comm[1] = 0x10;
707 comm[2] = 0x00;
708 comm[3] = 0x00;
709 comm[4] = 0x10;
710 comm[5] = 0x00;
711
712 data = comm + 6;
713 data[0] = 0x00; /* mode data length */
714 data[1] = 0x00; /* medium type */
715 data[2] = 0x00; /* device specific parameter */
716 data[3] = 0x00; /* block descriptor length */
717
718 data = comm + 10;
719 data[0] = 0x00; /* control page parameters */
720 data[1] = 0x0a; /* parameter length */
721 data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) |
722 ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01);
723 data[3] = 0x00; /* reserved */
724 data[4] = 0x00; /* reserved */
725
726 DBG (9, "artec_mode_select: mode %d\n", data[2]);
727 DBG (9, "artec_mode_select: sending mode command\n");
728 sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0);
729
730 DBG (9, "artec_mode_select: wait for scanner to come ready...\n");
731 return wait_ready (s->fd);
732 }
733
734
735 static SANE_Status
read_data(int fd, int data_type_code, u_char * dest, size_t * len)736 read_data (int fd, int data_type_code, u_char * dest, size_t * len)
737 {
738 static u_char read_6[10];
739
740 DBG (7, "read_data()\n");
741
742 memset (read_6, 0, sizeof (read_6));
743 read_6[0] = 0x28;
744 read_6[2] = data_type_code;
745 read_6[6] = *len >> 16;
746 read_6[7] = *len >> 8;
747 read_6[8] = *len;
748
749 return (sanei_scsi_cmd (fd, read_6, sizeof (read_6), dest, len));
750 }
751
752 static int
artec_get_status(int fd)753 artec_get_status (int fd)
754 {
755 u_char write_10[10];
756 u_char read_12[12];
757 size_t nread;
758
759 DBG (7, "artec_get_status()\n");
760
761 nread = 12;
762
763 memset (write_10, 0, 10);
764 write_10[0] = 0x34;
765 write_10[8] = 0x0c;
766
767 sanei_scsi_cmd (fd, write_10, 10, read_12, &nread);
768
769 nread = (read_12[9] << 16) + (read_12[10] << 8) + read_12[11];
770 DBG (9, "artec_status: %lu\n", (u_long) nread);
771
772 return (nread);
773 }
774
775 static SANE_Status
artec_reverse_line(SANE_Handle handle, SANE_Byte * data)776 artec_reverse_line (SANE_Handle handle, SANE_Byte * data)
777 {
778 ARTEC_Scanner *s = handle;
779 SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */
780 SANE_Byte *to, *from;
781 int len;
782
783 DBG (8, "artec_reverse_line()\n");
784
785 len = s->params.bytes_per_line;
786 memcpy (tmp_buf, data, len);
787
788 if (s->params.format == SANE_FRAME_RGB) /* RGB format */
789 {
790 for (from = tmp_buf, to = data + len - 3;
791 to >= data;
792 to -= 3, from += 3)
793 {
794 *(to + 0) = *(from + 0); /* copy the R byte */
795 *(to + 1) = *(from + 1); /* copy the G byte */
796 *(to + 2) = *(from + 2); /* copy the B byte */
797 }
798 }
799 else if (s->params.format == SANE_FRAME_GRAY)
800 {
801 if (s->params.depth == 8) /* 256 color gray-scale */
802 {
803 for (from = tmp_buf, to = data + len; to >= data; to--, from++)
804 {
805 *to = *from;
806 }
807 }
808 else if (s->params.depth == 1) /* line art or halftone */
809 {
810 for (from = tmp_buf, to = data + len; to >= data; to--, from++)
811 {
812 *to = (((*from & 0x01) << 7) |
813 ((*from & 0x02) << 5) |
814 ((*from & 0x04) << 3) |
815 ((*from & 0x08) << 1) |
816 ((*from & 0x10) >> 1) |
817 ((*from & 0x20) >> 3) |
818 ((*from & 0x40) >> 5) |
819 ((*from & 0x80) >> 7));
820 }
821 }
822 }
823
824 return (SANE_STATUS_GOOD);
825 }
826
827
828 #if 0
829 static SANE_Status
830 artec_byte_rgb_to_line_rgb (SANE_Byte * data, SANE_Int len)
831 {
832 SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */
833 int count, from;
834
835 DBG (8, "artec_byte_rgb_to_line_rgb()\n");
836
837 /* copy the RGBRGBRGBRGBRGB... formatted data to our temp buffer */
838 memcpy (tmp_buf, data, len * 3);
839
840 /* now copy back to *data in RRRRRRRGGGGGGGBBBBBBB format */
841 for (count = 0, from = 0; count < len; count++, from += 3)
842 {
843 data[count] = tmp_buf[from]; /* R byte */
844 data[count + len] = tmp_buf[from + 1]; /* G byte */
845 data[count + (len * 2)] = tmp_buf[from + 2]; /* B byte */
846 }
847
848 return (SANE_STATUS_GOOD);
849 }
850 #endif
851
852 static SANE_Status
artec_line_rgb_to_byte_rgb(SANE_Byte * data, SANE_Int len)853 artec_line_rgb_to_byte_rgb (SANE_Byte * data, SANE_Int len)
854 {
855 SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */
856 int count, to;
857
858 DBG (8, "artec_line_rgb_to_byte_rgb()\n");
859
860 /* copy the rgb data to our temp buffer */
861 memcpy (tmp_buf, data, len * 3);
862
863 /* now copy back to *data in RGB format */
864 for (count = 0, to = 0; count < len; count++, to += 3)
865 {
866 data[to] = tmp_buf[count]; /* R byte */
867 data[to + 1] = tmp_buf[count + len]; /* G byte */
868 data[to + 2] = tmp_buf[count + (len * 2)]; /* B byte */
869 }
870
871 return (SANE_STATUS_GOOD);
872 }
873
874 static SANE_Byte **line_buffer = NULL;
875 static SANE_Byte *tmp_line_buf = NULL;
876 static SANE_Int r_buf_lines;
877 static SANE_Int g_buf_lines;
878
879 static SANE_Status
artec_buffer_line_offset(SANE_Handle handle, SANE_Int line_offset, SANE_Byte * data, size_t * len)880 artec_buffer_line_offset (SANE_Handle handle, SANE_Int line_offset,
881 SANE_Byte * data, size_t * len)
882 {
883 ARTEC_Scanner *s = handle;
884 static SANE_Int width;
885 static SANE_Int cur_line;
886 SANE_Byte *tmp_buf_ptr;
887 SANE_Byte *grn_ptr;
888 SANE_Byte *blu_ptr;
889 SANE_Byte *out_ptr;
890 int count;
891
892 DBG (8, "artec_buffer_line_offset()\n");
893
894 if (*len == 0)
895 return (SANE_STATUS_GOOD);
896
897 if (tmp_line_buf == NULL)
898 {
899 width = *len / 3;
900 cur_line = 0;
901
902 DBG (9, "buffer_line_offset: offset = %d, len = %lu\n",
903 line_offset, (u_long) * len);
904
905 tmp_line_buf = malloc (*len);
906 if (tmp_line_buf == NULL)
907 {
908 DBG (1, "couldn't allocate memory for temp line buffer\n");
909 return (SANE_STATUS_NO_MEM);
910 }
911
912 r_buf_lines = line_offset * 2;
913 g_buf_lines = line_offset;
914
915 line_buffer = malloc (r_buf_lines * sizeof (SANE_Byte *));
916 if (line_buffer == NULL)
917 {
918 DBG (1, "couldn't allocate memory for line buffer pointers\n");
919 return (SANE_STATUS_NO_MEM);
920 }
921
922 for (count = 0; count < r_buf_lines; count++)
923 {
924 line_buffer[count] = malloc ((*len) * sizeof (SANE_Byte));
925 if (line_buffer[count] == NULL)
926 {
927 DBG (1, "couldn't allocate memory for line buffer %d\n",
928 count);
929 return (SANE_STATUS_NO_MEM);
930 }
931 }
932
933 DBG (9, "buffer_line_offset: r lines = %d, g lines = %d\n",
934 r_buf_lines, g_buf_lines);
935 }
936
937 cur_line++;
938
939 if (r_buf_lines > 0)
940 {
941 if (cur_line > r_buf_lines)
942 {
943 /* copy the Red and Green portions out of the buffer */
944 /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */
945 if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)
946 {
947 /* get the red line info from r_buf_lines ago */
948 memcpy (tmp_line_buf, line_buffer[0], width);
949
950 /* get the green line info from g_buf_lines ago */
951 memcpy (tmp_line_buf + width, &line_buffer[line_offset][width],
952 width);
953 }
954 else
955 {
956 /* get the red line info from r_buf_lines ago as a whole line */
957 memcpy (tmp_line_buf, line_buffer[0], *len);
958
959 /* scanner returns RGBRGBRGB format so we do a loop for green */
960 grn_ptr = &line_buffer[line_offset][1];
961 out_ptr = tmp_line_buf + 1;
962 for (count = 0; count < width; count++)
963 {
964 *out_ptr = *grn_ptr; /* copy green pixel */
965
966 grn_ptr += 3;
967 out_ptr += 3;
968 }
969 }
970 }
971
972 /* move all the buffered lines down (just move the ptrs for speed) */
973 tmp_buf_ptr = line_buffer[0];
974 for (count = 0; count < (r_buf_lines - 1); count++)
975 {
976 line_buffer[count] = line_buffer[count + 1];
977 }
978 line_buffer[r_buf_lines - 1] = tmp_buf_ptr;
979
980 /* insert the new line data at the end of our FIFO */
981 memcpy (line_buffer[r_buf_lines - 1], data, *len);
982
983 if (cur_line > r_buf_lines)
984 {
985 /* copy the Red and Green portions out of the buffer */
986 /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */
987 if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)
988 {
989 /* copy the red and green data in with the original blue */
990 memcpy (data, tmp_line_buf, width * 2);
991 }
992 else
993 {
994 /* scanner returns RGBRGBRGB format so we have to do a loop */
995 /* copy the blue data into our temp buffer then copy full */
996 /* temp buffer overtop of input data */
997 if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR)
998 {
999 blu_ptr = data;
1000 out_ptr = tmp_line_buf;
1001 }
1002 else
1003 {
1004 blu_ptr = data + 2;
1005 out_ptr = tmp_line_buf + 2;
1006 }
1007
1008 for (count = 0; count < width; count++)
1009 {
1010 *out_ptr = *blu_ptr; /* copy blue pixel */
1011
1012 blu_ptr += 3;
1013 out_ptr += 3;
1014 }
1015
1016 /* now just copy tmp_line_buf back over original data */
1017 memcpy (data, tmp_line_buf, *len);
1018 }
1019 }
1020 else
1021 {
1022 /* if in the first r_buf_lines, then don't return anything */
1023 *len = 0;
1024 }
1025 }
1026
1027 return (SANE_STATUS_GOOD);
1028 }
1029
1030 static SANE_Status
artec_buffer_line_offset_free(void)1031 artec_buffer_line_offset_free (void)
1032 {
1033 int count;
1034
1035 DBG (7, "artec_buffer_line_offset_free()\n");
1036
1037 free (tmp_line_buf);
1038 tmp_line_buf = NULL;
1039
1040 for (count = 0; count < r_buf_lines; count++)
1041 {
1042 free (line_buffer[count]);
1043 }
1044 free (line_buffer);
1045 line_buffer = NULL;
1046
1047 return (SANE_STATUS_GOOD);
1048 }
1049
1050
1051 #if 0
1052 static SANE_Status
1053 artec_read_gamma_table (SANE_Handle handle)
1054 {
1055 ARTEC_Scanner *s = handle;
1056 char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */
1057 char *data;
1058 char prt_buf[128];
1059 char tmp_buf[128];
1060 int i;
1061
1062 DBG (7, "artec_read_gamma_table()\n");
1063
1064 memset (write_6, 0, sizeof (*write_6));
1065
1066 write_6[0] = 0x28; /* read data code */
1067
1068 /* FIXME: AT12 and AM12S use 0x0E for reading all channels of data */
1069 write_6[2] = 0x03; /* data type code "gamma data" */
1070
1071 write_6[6] = (s->gamma_length + 9) >> 16;
1072 write_6[7] = (s->gamma_length + 9) >> 8;
1073 write_6[8] = (s->gamma_length + 9);
1074
1075 /* FIXME: AT12 and AM12S have one less byte so use 18 */
1076 if ((!strcmp (s->hw->sane.model, "AT12")) ||
1077 (!strcmp (s->hw->sane.model, "AM12S")))
1078 {
1079 data = write_6 + 18;
1080 }
1081 else
1082 {
1083 data = write_6 + 19;
1084 }
1085
1086 /* FIXME: AT12 & AM12S ignore this, it's a reserved field */
1087 write_6[10] = 0x08; /* bitmask, bit 3 means mono type */
1088
1089 if (!s->val[OPT_CUSTOM_GAMMA].w)
1090 {
1091 write_6[11] = 1; /* internal gamma table #1 (hope this is default) */
1092 }
1093
1094 DBG( 9, "Gamma Table\n" );
1095 DBG( 9, "==================================\n" );
1096
1097 prt_buf[0] = '\0';
1098 for (i = 0; i < s->gamma_length; i++)
1099 {
1100 if (DBG_LEVEL >= 9)
1101 {
1102 if (!(i % 16))
1103 {
1104 if ( prt_buf[0] )
1105 {
1106 strcat( prt_buf, "\n" );
1107 DBG( 9, "%s", prt_buf );
1108 }
1109 sprintf (prt_buf, "%02x: ", i);
1110 }
1111 sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]);
1112 strcat (prt_buf, tmp_buf );
1113 }
1114
1115 data[i] = s->gamma_table[0][i];
1116 }
1117
1118 if ( prt_buf[0] )
1119 {
1120 strcat( prt_buf, "\n" );
1121 DBG( 9, "%s", prt_buf );
1122 }
1123
1124 if ((!strcmp (s->hw->sane.model, "AT12")) ||
1125 (!strcmp (s->hw->sane.model, "AM12S")))
1126 {
1127 return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0));
1128 }
1129 else
1130 {
1131 return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0));
1132 }
1133 }
1134 #endif
1135
1136 static SANE_Status
artec_send_gamma_table(SANE_Handle handle)1137 artec_send_gamma_table (SANE_Handle handle)
1138 {
1139 ARTEC_Scanner *s = handle;
1140 char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */
1141 char *data;
1142 char prt_buf[128];
1143 char tmp_buf[128];
1144 int i;
1145
1146 DBG (7, "artec_send_gamma_table()\n");
1147
1148 memset (write_6, 0, sizeof (*write_6));
1149
1150 write_6[0] = 0x2a; /* send data code */
1151
1152 if (s->hw->setwindow_cmd_size > 55)
1153 {
1154 /* newer scanners support sending 3 channels of gamma, or populating all */
1155 /* 3 channels with same data by using code 0x0e */
1156 write_6[2] = 0x0e;
1157 }
1158 else
1159 {
1160 /* older scanners only support 1 channel of gamma data using code 0x3 */
1161 write_6[2] = 0x03;
1162 }
1163
1164 /* FIXME: AT12 & AM!2S ignore this, it's a reserved field */
1165 write_6[10] = 0x08; /* bitmask, bit 3 means mono type */
1166
1167 if (!s->val[OPT_CUSTOM_GAMMA].w)
1168 {
1169 write_6[6] = 9 >> 16;
1170 write_6[7] = 9 >> 8;
1171 write_6[8] = 9;
1172 write_6[11] = 1; /* internal gamma table #1 (hope this is default) */
1173
1174 return (sanei_scsi_cmd (s->fd, write_6, 10 + 9, 0, 0));
1175 }
1176 else
1177 {
1178 write_6[6] = (s->gamma_length + 9) >> 16;
1179 write_6[7] = (s->gamma_length + 9) >> 8;
1180 write_6[8] = (s->gamma_length + 9);
1181
1182 DBG( 9, "Gamma Table\n" );
1183 DBG( 9, "==================================\n" );
1184
1185 /* FIXME: AT12 and AM12S have one less byte so use 18 */
1186 if ((!strcmp (s->hw->sane.model, "AT12")) ||
1187 (!strcmp (s->hw->sane.model, "AM12S")))
1188 {
1189 data = write_6 + 18;
1190 }
1191 else
1192 {
1193 data = write_6 + 19;
1194 }
1195
1196 prt_buf[0] = '\0';
1197 for (i = 0; i < s->gamma_length; i++)
1198 {
1199 if (DBG_LEVEL >= 9)
1200 {
1201 if (!(i % 16))
1202 {
1203 if ( prt_buf[0] )
1204 {
1205 strcat( prt_buf, "\n" );
1206 DBG( 9, "%s", prt_buf );
1207 }
1208 sprintf (prt_buf, "%02x: ", i);
1209 }
1210 sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]);
1211 strcat (prt_buf, tmp_buf );
1212 }
1213
1214 data[i] = s->gamma_table[0][i];
1215 }
1216
1217 data[s->gamma_length - 1] = 0;
1218
1219 if ( prt_buf[0] )
1220 {
1221 strcat( prt_buf, "\n" );
1222 DBG( 9, "%s", prt_buf );
1223 }
1224
1225 /* FIXME: AT12 and AM12S have one less byte so use 18 */
1226 if ((!strcmp (s->hw->sane.model, "AT12")) ||
1227 (!strcmp (s->hw->sane.model, "AM12S")))
1228 {
1229 return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0));
1230 }
1231 else
1232 {
1233 return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0));
1234 }
1235 }
1236 }
1237
1238 static SANE_Status
artec_set_scan_window(SANE_Handle handle)1239 artec_set_scan_window (SANE_Handle handle)
1240 {
1241 ARTEC_Scanner *s = handle;
1242 char write_6[4096];
1243 unsigned char *data;
1244 int counter;
1245 int reversed_x;
1246 int max_x;
1247
1248 DBG (7, "artec_set_scan_window()\n");
1249
1250 /*
1251 * if we can, start before the desired window since we have to throw away
1252 * s->line_offset number of rows because of the RGB fixup.
1253 */
1254 if ((s->line_offset) &&
1255 (s->tl_y) &&
1256 (s->tl_y >= (s->line_offset * 2)))
1257 {
1258 s->tl_y -= (s->line_offset * 2);
1259 }
1260
1261 data = (unsigned char *)write_6 + 10;
1262
1263 DBG (5, "Scan window info:\n");
1264 DBG (5, " X resolution: %5d (%d-%d)\n",
1265 s->x_resolution, ARTEC_MIN_X (s->hw), ARTEC_MAX_X (s->hw));
1266 DBG (5, " Y resolution: %5d (%d-%d)\n",
1267 s->y_resolution, ARTEC_MIN_Y (s->hw), ARTEC_MAX_Y (s->hw));
1268 DBG (5, " TL_X (pixel): %5d\n",
1269 s->tl_x);
1270 DBG (5, " TL_Y (pixel): %5d\n",
1271 s->tl_y);
1272 DBG (5, " Width : %5d (%d-%d)\n",
1273 s->params.pixels_per_line,
1274 s->hw->x_range.min,
1275 (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) *
1276 s->x_resolution));
1277 DBG (5, " Height : %5d (%d-%d)\n",
1278 s->params.lines,
1279 s->hw->y_range.min,
1280 (int) ((SANE_UNFIX (s->hw->y_range.max) / MM_PER_INCH) *
1281 s->y_resolution));
1282
1283 DBG (5, " Image Comp. : %s\n", s->mode);
1284 DBG (5, " Line Offset : %lu\n", (u_long) s->line_offset);
1285
1286 memset (write_6, 0, 4096);
1287 write_6[0] = 0x24;
1288 write_6[8] = s->hw->setwindow_cmd_size; /* total size of command */
1289
1290 /* beginning of set window data header */
1291 /* actual SCSI command data byte count */
1292 data[7] = s->hw->setwindow_cmd_size - 8;
1293
1294 /* x resolution */
1295 data[10] = s->x_resolution >> 8;
1296 data[11] = s->x_resolution;
1297
1298 /* y resolution */
1299 data[12] = s->y_resolution >> 8;
1300 data[13] = s->y_resolution;
1301
1302 if ( s->hw->flags & ARTEC_FLAG_REVERSE_WINDOW )
1303 {
1304 /* top left X value */
1305 /* the select area is flipped across the page, so we have to do some */
1306 /* calculation here to get the real starting X value */
1307 max_x = (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) *
1308 s->x_resolution);
1309 reversed_x = max_x - s->tl_x - s->params.pixels_per_line;
1310
1311 data[14] = reversed_x >> 24;
1312 data[15] = reversed_x >> 16;
1313 data[16] = reversed_x >> 8;
1314 data[17] = reversed_x;
1315 }
1316 else
1317 {
1318 /* top left X value */
1319 data[14] = s->tl_x >> 24;
1320 data[15] = s->tl_x >> 16;
1321 data[16] = s->tl_x >> 8;
1322 data[17] = s->tl_x;
1323 }
1324
1325 /* top left Y value */
1326 data[18] = s->tl_y >> 24;
1327 data[19] = s->tl_y >> 16;
1328 data[20] = s->tl_y >> 8;
1329 data[21] = s->tl_y;
1330
1331
1332 /* width */
1333 data[22] = s->params.pixels_per_line >> 24;
1334 data[23] = s->params.pixels_per_line >> 16;
1335 data[24] = s->params.pixels_per_line >> 8;
1336 data[25] = s->params.pixels_per_line;
1337
1338 /* height */
1339 data[26] = (s->params.lines + (s->line_offset * 2)) >> 24;
1340 data[27] = (s->params.lines + (s->line_offset * 2)) >> 16;
1341 data[28] = (s->params.lines + (s->line_offset * 2)) >> 8;
1342 data[29] = (s->params.lines + (s->line_offset * 2));
1343
1344 /* misc. single-byte settings */
1345 /* brightness */
1346 if (s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS)
1347 data[30] = s->val[OPT_BRIGHTNESS].w;
1348
1349 data[31] = s->val[OPT_THRESHOLD].w; /* threshold */
1350
1351 /* contrast */
1352 if (s->hw->flags & ARTEC_FLAG_OPT_CONTRAST)
1353 data[32] = s->val[OPT_CONTRAST].w;
1354
1355 /*
1356 * byte 33 is mode
1357 * byte 37 bit 7 is "negative" setting
1358 */
1359 if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)
1360 {
1361 data[33] = ARTEC_COMP_LINEART;
1362 data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80;
1363 }
1364 else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
1365 {
1366 data[33] = ARTEC_COMP_HALFTONE;
1367 data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80;
1368 }
1369 else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
1370 {
1371 data[33] = ARTEC_COMP_GRAY;
1372 data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0;
1373 }
1374 else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)
1375 {
1376 data[33] = ARTEC_COMP_COLOR;
1377 data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0;
1378 }
1379
1380 data[34] = s->params.depth; /* bits per pixel */
1381
1382 if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN)
1383 {
1384 data[35] = artec_get_str_index (halftone_pattern_list,
1385 s->val[OPT_HALFTONE_PATTERN].s); /* halftone pattern */
1386 }
1387
1388 /* user supplied halftone pattern not supported for now so override with */
1389 /* 8x8 Bayer */
1390 if (data[35] == 0)
1391 {
1392 data[35] = 4;
1393 }
1394
1395 /* NOTE: AT12 doesn't support mono according to docs. */
1396 data[48] = artec_get_str_index (filter_type_list,
1397 s->val[OPT_FILTER_TYPE].s); /* filter mode */
1398
1399 if (s->hw->setwindow_cmd_size > 55)
1400 {
1401 data[48] = 0x2; /* DB filter type green for AT12,see above */
1402
1403 if (s->hw->flags & ARTEC_FLAG_SC_BUFFERS_LINES)
1404 {
1405 /* FIXME: guessing at this value, use formula instead */
1406 data[55] = 0x00; /* buffer full line count */
1407 data[56] = 0x00; /* buffer full line count */
1408 data[57] = 0x00; /* buffer full line count */
1409 data[58] = 0x0a; /* buffer full line count */
1410
1411 /* FIXME: guessing at this value, use formula instead */
1412 data[59] = 0x00; /* access line count */
1413 data[60] = 0x00; /* access line count */
1414 data[61] = 0x00; /* access line count */
1415 data[62] = 0x0a; /* access line count */
1416 }
1417
1418 if (s->hw->flags & ARTEC_FLAG_SC_HANDLES_OFFSET)
1419 {
1420 /* DB : following fields : high order bit (0x80) is enable */
1421 /* scanner handles line offset fixup, 0 = driver handles */
1422 data[63] = 0x80;
1423 }
1424
1425 if ((s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING) &&
1426 (s->val[OPT_PIXEL_AVG].w))
1427 {
1428 /* enable pixel average function */
1429 data[64] = 0x80;
1430 }
1431 else
1432 {
1433 /* disable pixel average function */
1434 data[64] = 0;
1435 }
1436
1437 if ((s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE) &&
1438 (s->val[OPT_EDGE_ENH].w))
1439 {
1440 /* enable lineart edge enhancement function */
1441 data[65] = 0x80;
1442 }
1443 else
1444 {
1445 /* disable lineart edge enhancement function */
1446 data[65] = 0;
1447 }
1448
1449 /* data is R-G-B format, 0x80 = G-B-R format (reversed) */
1450 data[66] = 0;
1451 }
1452
1453 DBG (50, "Set Window data : \n");
1454 for (counter = 0; counter < s->hw->setwindow_cmd_size; counter++)
1455 {
1456 DBG (50, " byte %2d = %02x \n", counter, data[counter] & 0xff); /* DB */
1457 }
1458 DBG (50, "\n");
1459
1460 /* set the scan window */
1461 return (sanei_scsi_cmd (s->fd, write_6, 10 +
1462 s->hw->setwindow_cmd_size, 0, 0));
1463 }
1464
1465 static SANE_Status
artec_start_scan(SANE_Handle handle)1466 artec_start_scan (SANE_Handle handle)
1467 {
1468 ARTEC_Scanner *s = handle;
1469 char write_7[7];
1470
1471 DBG (7, "artec_start_scan()\n");
1472
1473 /* setup cmd to start scanning */
1474 memset (write_7, 0, 7);
1475 write_7[0] = 0x1b; /* code to start scan */
1476
1477 /* FIXME: need to make this a flag */
1478 if (!strcmp (s->hw->sane.model, "AM12S"))
1479 {
1480 /* start the scan */
1481 return (sanei_scsi_cmd (s->fd, write_7, 6, 0, 0));
1482 }
1483 else
1484 {
1485 write_7[4] = 0x01; /* need to send 1 data byte */
1486
1487 /* start the scan */
1488 return (sanei_scsi_cmd (s->fd, write_7, 7, 0, 0));
1489 }
1490 }
1491
1492 static SANE_Status
artec_software_rgb_calibrate(SANE_Handle handle, SANE_Byte * buf, int lines)1493 artec_software_rgb_calibrate (SANE_Handle handle, SANE_Byte * buf, int lines)
1494 {
1495 ARTEC_Scanner *s = handle;
1496 int line, i, loop, offset;
1497
1498 DBG (7, "artec_software_rgb_calibrate()\n");
1499
1500 for (line = 0; line < lines; line++)
1501 {
1502 i = 0;
1503 offset = 0;
1504
1505 if (s->x_resolution == 200)
1506 {
1507 /* skip ever 3rd byte, -= causes us to go down in count */
1508 if ((s->tl_x % 3) == 0)
1509 offset -= 1;
1510 }
1511 else
1512 {
1513 /* round down to the previous pixel */
1514 offset += ((s->tl_x / (300 / s->x_resolution)) *
1515 (300 / s->x_resolution));
1516 }
1517
1518 for (loop = 0; loop < s->params.pixels_per_line; loop++)
1519 {
1520 if ((DBG_LEVEL == 100) &&
1521 (loop < 100))
1522 {
1523 DBG (100, " %2d-%4d R (%4d,%4d): %d * %5.2f = %d\n",
1524 line, loop, i, offset, buf[i],
1525 s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset],
1526 (int) (buf[i] *
1527 s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset]));
1528 }
1529 buf[i] = buf[i] *
1530 s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset];
1531 i++;
1532
1533 if ((DBG_LEVEL == 100) &&
1534 (loop < 100))
1535 {
1536 DBG (100, " G (%4d,%4d): %d * %5.2f = %d\n",
1537 i, offset, buf[i],
1538 s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset],
1539 (int) (buf[i] *
1540 s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset]));
1541 }
1542 buf[i] = buf[i] *
1543 s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset];
1544 i++;
1545
1546 if ((DBG_LEVEL == 100) &&
1547 (loop < 100))
1548 {
1549 DBG (100, " B (%4d,%4d): %d * %5.2f = %d\n",
1550 i, offset, buf[i],
1551 s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset],
1552 (int) (buf[i] *
1553 s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset]));
1554 }
1555 buf[i] = buf[i] *
1556 s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset];
1557 i++;
1558
1559 if (s->x_resolution == 200)
1560 {
1561 offset += 1;
1562
1563 /* skip every 3rd byte */
1564 if (((offset + 1) % 3) == 0)
1565 offset += 1;
1566 }
1567 else
1568 {
1569 offset += (300 / s->x_resolution);
1570 }
1571 }
1572 }
1573
1574 return (SANE_STATUS_GOOD);
1575 }
1576
1577 static SANE_Status
artec_calibrate_shading(SANE_Handle handle)1578 artec_calibrate_shading (SANE_Handle handle)
1579 {
1580 ARTEC_Scanner *s = handle;
1581 SANE_Status status; /* DB added */
1582 u_char buf[76800]; /* should be big enough */
1583 size_t len;
1584 SANE_Word save_x_resolution;
1585 SANE_Word save_pixels_per_line;
1586 int i;
1587
1588 DBG (7, "artec_calibrate_shading()\n");
1589
1590 if (s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB)
1591 {
1592 /* this method scans in 4 lines each of Red, Green, and Blue */
1593 /* after reading line of shading data, generate data for software */
1594 /* calibration so we have it if user requests */
1595 len = 4 * 2592; /* 4 lines of data, 2592 pixels wide */
1596
1597 if ( DBG_LEVEL == 100 )
1598 DBG (100, "RED Software Calibration data\n");
1599
1600 read_data (s->fd, ARTEC_DATA_RED_SHADING, buf, &len);
1601 for (i = 0; i < 2592; i++)
1602 {
1603 s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i] =
1604 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4);
1605 if (DBG_LEVEL == 100)
1606 {
1607 DBG (100,
1608 " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n",
1609 i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776],
1610 s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i]);
1611 }
1612 }
1613
1614 if (DBG_LEVEL == 100)
1615 {
1616 DBG (100, "GREEN Software Calibration data\n");
1617 }
1618
1619 read_data (s->fd, ARTEC_DATA_GREEN_SHADING, buf, &len);
1620 for (i = 0; i < 2592; i++)
1621 {
1622 s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i] =
1623 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4);
1624 if (DBG_LEVEL == 100)
1625 {
1626 DBG (100,
1627 " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n",
1628 i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776],
1629 s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i]);
1630 }
1631 }
1632
1633 if (DBG_LEVEL == 100)
1634 {
1635 DBG (100, "BLUE Software Calibration data\n");
1636 }
1637
1638 read_data (s->fd, ARTEC_DATA_BLUE_SHADING, buf, &len);
1639 for (i = 0; i < 2592; i++)
1640 {
1641 s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i] =
1642 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4);
1643 if (DBG_LEVEL == 100)
1644 {
1645 DBG (100,
1646 " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n",
1647 i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776],
1648 s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i]);
1649 }
1650 }
1651 }
1652 else if (s->hw->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE)
1653 {
1654 /* this method scans black, then white data */
1655 len = 3 * 5100; /* 1 line of data, 5100 pixels wide, RGB data */
1656 read_data (s->fd, ARTEC_DATA_DARK_SHADING, buf, &len);
1657 save_x_resolution = s->x_resolution;
1658 s->x_resolution = 600;
1659 save_pixels_per_line = s->params.pixels_per_line;
1660 s->params.pixels_per_line = ARTEC_MAX_X (s->hw);
1661 s->params.pixels_per_line = 600 * 8.5; /* ?this? or ?above line? */
1662 /* DB added wait_ready */
1663 status = wait_ready (s->fd);
1664 if (status != SANE_STATUS_GOOD)
1665 {
1666 DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status));
1667 return status;
1668 }
1669 /* next line should use ARTEC_DATA_WHITE_SHADING_TRANS if using ADF */
1670 read_data (s->fd, ARTEC_DATA_WHITE_SHADING_OPT, buf, &len);
1671 s->x_resolution = save_x_resolution;
1672 s->params.pixels_per_line = save_pixels_per_line;
1673 }
1674
1675 return (SANE_STATUS_GOOD);
1676 }
1677
1678
1679 static SANE_Status
end_scan(SANE_Handle handle)1680 end_scan (SANE_Handle handle)
1681 {
1682 ARTEC_Scanner *s = handle;
1683 /* DB
1684 uint8_t write_6[6] =
1685 {0x1B, 0, 0, 0, 0, 0};
1686 */
1687
1688 DBG (7, "end_scan()\n");
1689
1690 s->scanning = SANE_FALSE;
1691
1692 /* if (s->this_pass == 3) */
1693 s->this_pass = 0;
1694
1695 if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) &&
1696 (tmp_line_buf != NULL))
1697 {
1698 artec_buffer_line_offset_free ();
1699 }
1700
1701 /* DB
1702 return (sanei_scsi_cmd (s->fd, write_6, 6, 0, 0));
1703 */
1704 return abort_scan (s);
1705 }
1706
1707
1708 static SANE_Status
artec_get_cap_data(ARTEC_Device * dev, int fd)1709 artec_get_cap_data (ARTEC_Device * dev, int fd)
1710 {
1711 int cap_model, loop;
1712 u_char cap_buf[256]; /* buffer for cap data */
1713
1714 DBG (7, "artec_get_cap_data()\n");
1715
1716 /* DB always use the hard-coded capability info first
1717 * if we get cap data from the scanner, we override */
1718 cap_model = -1;
1719 for (loop = 0; loop < NELEMS (cap_data); loop++)
1720 {
1721 if (strcmp (cap_data[loop].model, dev->sane.model) == 0)
1722 {
1723 cap_model = loop;
1724 }
1725 }
1726
1727 if (cap_model == -1)
1728 {
1729 DBG (1, "unable to identify Artec model '%s', check artec.c\n",
1730 dev->sane.model);
1731 return (SANE_STATUS_UNSUPPORTED);
1732 }
1733
1734 dev->x_range.min = 0;
1735 dev->x_range.max = SANE_FIX (cap_data[cap_model].width) * MM_PER_INCH;
1736 dev->x_range.quant = 1;
1737
1738 dev->width = cap_data[cap_model].width;
1739
1740 dev->y_range.min = 0;
1741 dev->y_range.max = SANE_FIX (cap_data[cap_model].height) * MM_PER_INCH;
1742 dev->y_range.quant = 1;
1743
1744 dev->height = cap_data[cap_model].height;
1745
1746 artec_str_list_to_word_list (&dev->horz_resolution_list,
1747 cap_data[cap_model].horz_resolution_str);
1748
1749 artec_str_list_to_word_list (&dev->vert_resolution_list,
1750 cap_data[cap_model].vert_resolution_str);
1751
1752 dev->contrast_range.min = 0;
1753 dev->contrast_range.max = 255;
1754 dev->contrast_range.quant = 1;
1755
1756 dev->brightness_range.min = 0;
1757 dev->brightness_range.max = 255;
1758 dev->brightness_range.quant = 1;
1759
1760 dev->threshold_range.min = 0;
1761 dev->threshold_range.max = 255;
1762 dev->threshold_range.quant = 1;
1763
1764 dev->sane.type = cap_data[cap_model].type;
1765
1766 dev->max_read_size = cap_data[cap_model].max_read_size;
1767
1768 dev->flags = cap_data[cap_model].flags;
1769
1770 switch (cap_data[cap_model].adc_bits)
1771 {
1772 case 8:
1773 dev->gamma_length = 256;
1774 break;
1775
1776 case 10:
1777 dev->gamma_length = 1024;
1778 break;
1779
1780 case 12:
1781 dev->gamma_length = 4096;
1782 break;
1783 }
1784
1785 dev->setwindow_cmd_size = cap_data[cap_model].setwindow_cmd_size;
1786
1787 if (dev->support_cap_data_retrieve) /* DB */
1788 {
1789 /* DB added reading capability data from scanner */
1790 char info[80]; /* for printing debugging info */
1791 size_t len = sizeof (cap_buf);
1792
1793 /* read the capability data from the scanner */
1794 DBG (9, "reading capability data from scanner...\n");
1795
1796 wait_ready (fd);
1797
1798 read_data (fd, ARTEC_DATA_CAPABILITY_DATA, cap_buf, &len);
1799
1800 DBG (50, "scanner capability data : \n");
1801 strncpy (info, (const char *) &cap_buf[0], 8);
1802 info[8] = '\0';
1803 DBG (50, " Vendor : %s\n", info);
1804 strncpy (info, (const char *) &cap_buf[8], 16);
1805 info[16] = '\0';
1806 DBG (50, " Device Name : %s\n", info);
1807 strncpy (info, (const char *) &cap_buf[24], 4);
1808 info[4] = '\0';
1809 DBG (50, " Version Number : %s\n", info);
1810 sprintf (info, "%d ", cap_buf[29]);
1811 DBG (50, " CCD Type : %s\n", info);
1812 sprintf (info, "%d ", cap_buf[30]);
1813 DBG (50, " AD Converter Type : %s\n", info);
1814 sprintf (info, "%d ", (cap_buf[31] << 8) | cap_buf[32]);
1815 DBG (50, " Buffer size : %s\n", info);
1816 sprintf (info, "%d ", cap_buf[33]);
1817 DBG (50, " Channels of RGB Gamma : %s\n", info);
1818 sprintf (info, "%d ", (cap_buf[34] << 8) | cap_buf[35]);
1819 DBG (50, " Opt. res. of R channel : %s\n", info);
1820 sprintf (info, "%d ", (cap_buf[36] << 8) | cap_buf[37]);
1821 DBG (50, " Opt. res. of G channel : %s\n", info);
1822 sprintf (info, "%d ", (cap_buf[38] << 8) | cap_buf[39]);
1823 DBG (50, " Opt. res. of B channel : %s\n", info);
1824 sprintf (info, "%d ", (cap_buf[40] << 8) | cap_buf[41]);
1825 DBG (50, " Min. Hor. Resolution : %s\n", info);
1826 sprintf (info, "%d ", (cap_buf[42] << 8) | cap_buf[43]);
1827 DBG (50, " Max. Vert. Resolution : %s\n", info);
1828 sprintf (info, "%d ", (cap_buf[44] << 8) | cap_buf[45]);
1829 DBG (50, " Min. Vert. Resolution : %s\n", info);
1830 sprintf (info, "%s ", cap_buf[46] == 0x80 ? "yes" : "no");
1831 DBG (50, " Chunky Data Format : %s\n", info);
1832 sprintf (info, "%s ", cap_buf[47] == 0x80 ? "yes" : "no");
1833 DBG (50, " RGB Data Format : %s\n", info);
1834 sprintf (info, "%s ", cap_buf[48] == 0x80 ? "yes" : "no");
1835 DBG (50, " BGR Data Format : %s\n", info);
1836 sprintf (info, "%d ", cap_buf[49]);
1837 DBG (50, " Line Offset : %s\n", info);
1838 sprintf (info, "%s ", cap_buf[50] == 0x80 ? "yes" : "no");
1839 DBG (50, " Channel Valid Sequence : %s\n", info);
1840 sprintf (info, "%s ", cap_buf[51] == 0x80 ? "yes" : "no");
1841 DBG (50, " True Gray : %s\n", info);
1842 sprintf (info, "%s ", cap_buf[52] == 0x80 ? "yes" : "no");
1843 DBG (50, " Force Host Not Do Shading : %s\n", info);
1844 sprintf (info, "%s ", cap_buf[53] == 0x00 ? "AT006" : "AT010");
1845 DBG (50, " ASIC : %s\n", info);
1846 sprintf (info, "%s ", cap_buf[54] == 0x82 ? "SCSI2" :
1847 cap_buf[54] == 0x81 ? "SCSI1" : "Parallel");
1848 DBG (50, " Interface : %s\n", info);
1849 sprintf (info, "%d ", (cap_buf[55] << 8) | cap_buf[56]);
1850 DBG (50, " Phys. Area Width : %s\n", info);
1851 sprintf (info, "%d ", (cap_buf[57] << 8) | cap_buf[58]);
1852 DBG (50, " Phys. Area Length : %s\n", info);
1853
1854 /* fill in the information we've got from the scanner */
1855
1856 dev->width = ((float) ((cap_buf[55] << 8) | cap_buf[56])) / 1000;
1857 dev->height = ((float) ((cap_buf[57] << 8) | cap_buf[58])) / 1000;
1858
1859 /* DB ----- */
1860 }
1861
1862 DBG (9, "Scanner capability info.\n");
1863 DBG (9, " Vendor : %s\n", dev->sane.vendor);
1864 DBG (9, " Model : %s\n", dev->sane.model);
1865 DBG (9, " Type : %s\n", dev->sane.type);
1866 DBG (5, " Width : %.2f inches\n", dev->width);
1867 DBG (9, " Height : %.2f inches\n", dev->height);
1868 DBG (9, " X Range(mm) : %d-%d\n",
1869 dev->x_range.min,
1870 (int) (SANE_UNFIX (dev->x_range.max)));
1871 DBG (9, " Y Range(mm) : %d-%d\n",
1872 dev->y_range.min,
1873 (int) (SANE_UNFIX (dev->y_range.max)));
1874
1875 DBG (9, " Horz. DPI : %d-%d\n", ARTEC_MIN_X (dev), ARTEC_MAX_X (dev));
1876 DBG (9, " Vert. DPI : %d-%d\n", ARTEC_MIN_Y (dev), ARTEC_MAX_Y (dev));
1877 DBG (9, " Contrast : %d-%d\n",
1878 dev->contrast_range.min, dev->contrast_range.max);
1879 DBG (9, " REQ Sh. Cal.: %d\n",
1880 dev->flags & ARTEC_FLAG_CALIBRATE ? 1 : 0);
1881 DBG (9, " REQ Ln. Offs: %d\n",
1882 dev->flags & ARTEC_FLAG_RGB_LINE_OFFSET ? 1 : 0);
1883 DBG (9, " REQ Ch. Shft: %d\n",
1884 dev->flags & ARTEC_FLAG_RGB_CHAR_SHIFT ? 1 : 0);
1885 DBG (9, " SetWind Size: %d\n",
1886 dev->setwindow_cmd_size);
1887 DBG (9, " Calib Method: %s\n",
1888 dev->flags & ARTEC_FLAG_CALIBRATE_RGB ? "RGB" :
1889 dev->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE ? "white/black" : "N/A");
1890
1891 return (SANE_STATUS_GOOD);
1892 }
1893
1894 static SANE_Status
dump_inquiry(unsigned char *result)1895 dump_inquiry (unsigned char *result)
1896 {
1897 int i;
1898 int j;
1899 char prt_buf[129] = "";
1900 char tmp_buf[129];
1901
1902 DBG (4, "dump_inquiry()\n");
1903
1904 DBG (4, " === SANE/Artec backend v%d.%d.%d ===\n",
1905 ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB);
1906 DBG (4, " ===== Scanner Inquiry Block =====\n");
1907 for (i = 0; i < 96; i += 16)
1908 {
1909 sprintf (prt_buf, "0x%02x: ", i);
1910 for (j = 0; j < 16; j++)
1911 {
1912 sprintf (tmp_buf, "%02x ", (int) result[i + j]);
1913 strcat( prt_buf, tmp_buf );
1914 }
1915 strcat( prt_buf, " ");
1916 for (j = 0; j < 16; j++)
1917 {
1918 sprintf (tmp_buf, "%c",
1919 isprint (result[i + j]) ? result[i + j] : '.');
1920 strcat( prt_buf, tmp_buf );
1921 }
1922 strcat( prt_buf, "\n" );
1923 DBG(4, "%s", prt_buf );
1924 }
1925
1926 return (SANE_STATUS_GOOD);
1927 }
1928
1929 static SANE_Status
attach(const char *devname, ARTEC_Device ** devp)1930 attach (const char *devname, ARTEC_Device ** devp)
1931 {
1932 char result[INQ_LEN];
1933 char product_revision[5];
1934 char temp_result[33];
1935 char *str, *t;
1936 int fd;
1937 SANE_Status status;
1938 ARTEC_Device *dev;
1939 size_t size;
1940
1941 DBG (7, "attach()\n");
1942
1943 for (dev = first_dev; dev; dev = dev->next)
1944 {
1945 if (strcmp (dev->sane.name, devname) == 0)
1946 {
1947 if (devp)
1948 *devp = dev;
1949 return (SANE_STATUS_GOOD);
1950 }
1951 }
1952
1953 DBG (6, "attach: opening %s\n", devname);
1954
1955 status = sanei_scsi_open (devname, &fd, sense_handler, NULL);
1956 if (status != SANE_STATUS_GOOD)
1957 {
1958 DBG (1, "attach: open failed (%s)\n", sane_strstatus (status));
1959 return (SANE_STATUS_INVAL);
1960 }
1961
1962 DBG (6, "attach: sending INQUIRY\n");
1963 size = sizeof (result);
1964 status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size);
1965 if (status != SANE_STATUS_GOOD || size < 16)
1966 {
1967 DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status));
1968 sanei_scsi_close (fd);
1969 return (status);
1970 }
1971
1972 /*
1973 * Check to see if this device is a scanner.
1974 */
1975 if (result[0] != 0x6)
1976 {
1977 DBG (1, "attach: device doesn't look like a scanner at all.\n");
1978 sanei_scsi_close (fd);
1979 return (SANE_STATUS_INVAL);
1980 }
1981
1982 /*
1983 * The BlackWidow BW4800SP is actually a rebadged AT3, with the vendor
1984 * string set to 8 spaces and the product to "Flatbed Scanner ". So,
1985 * if we have one of these, we'll make it look like an AT3.
1986 *
1987 * For now, to be on the safe side, we'll also check the version number
1988 * since BlackWidow seems to have left that intact as "1.90".
1989 *
1990 * Check that result[36] == 0x00 so we don't mistake a microtek scanner.
1991 */
1992 if ((result[36] == 0x00) &&
1993 (strncmp (result + 32, "1.90", 4) == 0) &&
1994 (strncmp (result + 8, " ", 8) == 0) &&
1995 (strncmp (result + 16, "Flatbed Scanner ", 16) == 0))
1996 {
1997 DBG (6, "Found BlackWidow BW4800SP scanner, setting up like AT3\n");
1998
1999 /* setup the vendor and product to mimic the Artec/Ultima AT3 */
2000 memcpy (result + 8, "ULTIMA", 6);
2001 memcpy (result + 16, "AT3 ", 16);
2002 }
2003
2004 /*
2005 * The Plustek 19200S is actually a rebadged AM12S, with the vendor string
2006 * set to 8 spaces.
2007 */
2008 if ((strncmp (result + 8, " ", 8) == 0) &&
2009 (strncmp (result + 16, "SCAN19200 ", 16) == 0))
2010 {
2011 DBG (6, "Found Plustek 19200S scanner, setting up like AM12S\n");
2012
2013 /* setup the vendor and product to mimic the Artec/Ultima AM12S */
2014 memcpy (result + 8, "ULTIMA", 6);
2015 memcpy (result + 16, "AM12S ", 16);
2016 }
2017
2018 /*
2019 * Check to see if they have forced a vendor and/or model string and
2020 * if so, fudge the inquiry results with that info. We do this right
2021 * before we check the inquiry results, otherwise we might not be forcing
2022 * anything.
2023 */
2024 if (artec_vendor[0] != 0x0)
2025 {
2026 /*
2027 * 1) copy the vendor string to our temp variable
2028 * 2) append 8 spaces to make sure we have at least 8 characters
2029 * 3) copy our fudged vendor string into the inquiry result.
2030 */
2031 strcpy (temp_result, artec_vendor);
2032 strcat (temp_result, " ");
2033 strncpy (result + 8, temp_result, 8);
2034 }
2035
2036 if (artec_model[0] != 0x0)
2037 {
2038 /*
2039 * 1) copy the model string to our temp variable
2040 * 2) append 16 spaces to make sure we have at least 16 characters
2041 * 3) copy our fudged model string into the inquiry result.
2042 */
2043 strcpy (temp_result, artec_model);
2044 strcat (temp_result, " ");
2045 strncpy (result + 16, temp_result, 16);
2046 }
2047
2048 /* are we really dealing with a scanner by ULTIMA/ARTEC? */
2049 if ((strncmp (result + 8, "ULTIMA", 6) != 0) &&
2050 (strncmp (result + 8, "ARTEC", 5) != 0))
2051 {
2052 DBG (1, "attach: device doesn't look like a Artec/ULTIMA scanner\n");
2053
2054 strncpy (temp_result, result + 8, 8);
2055 temp_result[8] = 0x0;
2056 DBG (1, "attach: FOUND vendor = '%s'\n", temp_result);
2057 strncpy (temp_result, result + 16, 16);
2058 temp_result[16] = 0x0;
2059 DBG (1, "attach: FOUND model = '%s'\n", temp_result);
2060
2061 sanei_scsi_close (fd);
2062 return (SANE_STATUS_INVAL);
2063 }
2064
2065 /* turn this wait OFF for now since it appears to cause problems with */
2066 /* AT12 models */
2067 /* turned off by creating an "if" that can never be true */
2068 if ( 1 == 2 ) {
2069 DBG (6, "attach: wait for scanner to come ready\n");
2070 status = wait_ready (fd);
2071
2072 if (status != SANE_STATUS_GOOD)
2073 {
2074 DBG (1, "attach: test unit ready failed (%s)\n",
2075 sane_strstatus (status));
2076 sanei_scsi_close (fd);
2077 return (status);
2078 }
2079 /* This is the end of the "if" that can never be true that in effect */
2080 /* comments out this wait_ready() call */
2081 }
2082 /* end of "if( 1 == 2 )" */
2083
2084 dev = malloc (sizeof (*dev));
2085 if (!dev)
2086 return (SANE_STATUS_NO_MEM);
2087
2088 memset (dev, 0, sizeof (*dev));
2089
2090 if (DBG_LEVEL >= 4)
2091 dump_inquiry ((unsigned char *) result);
2092
2093 dev->sane.name = strdup (devname);
2094
2095 /* get the model info */
2096 str = malloc (17);
2097 memcpy (str, result + 16, 16);
2098 str[16] = ' ';
2099 t = str + 16;
2100 while ((*t == ' ') && (t > str))
2101 {
2102 *t = '\0';
2103 t--;
2104 }
2105 dev->sane.model = str;
2106
2107 /* for some reason, the firmware revision is in the model info string on */
2108 /* the A6000C PLUS scanners instead of in it's proper place */
2109 if (strstr (str, "A6000C PLUS") == str)
2110 {
2111 str[11] = '\0';
2112 strncpy (product_revision, str + 12, 4);
2113 }
2114 else if (strstr (str, "AT3") == str)
2115 {
2116 str[3] = '\0';
2117 strncpy (product_revision, str + 8, 4);
2118 }
2119 else
2120 {
2121 /* get the product revision from it's normal place */
2122 strncpy (product_revision, result + 32, 4);
2123 }
2124 product_revision[4] = ' ';
2125 t = strchr (product_revision, ' ');
2126 if (t)
2127 *t = '\0';
2128 else
2129 t = "unknown revision";
2130
2131 /* get the vendor info */
2132 str = malloc (9);
2133 memcpy (str, result + 8, 8);
2134 str[8] = ' ';
2135 t = strchr (str, ' ');
2136 *t = '\0';
2137 dev->sane.vendor = str;
2138
2139 DBG (5, "scanner vendor: '%s', model: '%s', revision: '%s'\n",
2140 dev->sane.vendor, dev->sane.model, product_revision);
2141
2142 /* Artec docs say if bytes 36-43 = "ULTIMA ", then supports read cap. data */
2143 if (strncmp (result + 36, "ULTIMA ", 8) == 0)
2144 {
2145 DBG (5, "scanner supports read capability data function\n");
2146 dev->support_cap_data_retrieve = SANE_TRUE;
2147 }
2148 else
2149 {
2150 DBG (5, "scanner does NOT support read capability data function\n");
2151 dev->support_cap_data_retrieve = SANE_FALSE;
2152 }
2153
2154 DBG (6, "attach: getting scanner capability data\n");
2155 status = artec_get_cap_data (dev, fd);
2156 if (status != SANE_STATUS_GOOD)
2157 {
2158 DBG (1, "attach: artec_get_cap_data failed (%s)\n",
2159 sane_strstatus (status));
2160 sanei_scsi_close (fd);
2161 return (status);
2162 }
2163
2164 sanei_scsi_close (fd);
2165
2166 ++num_devices;
2167 dev->next = first_dev;
2168 first_dev = dev;
2169
2170 if (devp)
2171 *devp = dev;
2172
2173 return (SANE_STATUS_GOOD);
2174 }
2175
2176 static SANE_Status
init_options(ARTEC_Scanner * s)2177 init_options (ARTEC_Scanner * s)
2178 {
2179 int i;
2180
2181 DBG (7, "init_options()\n");
2182
2183 memset (s->opt, 0, sizeof (s->opt));
2184 memset (s->val, 0, sizeof (s->val));
2185
2186 for (i = 0; i < NUM_OPTIONS; ++i)
2187 {
2188 s->opt[i].size = sizeof (SANE_Word);
2189 s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2190 }
2191
2192 s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2193 s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2194 s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2195 s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2196 s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
2197
2198 /* "Mode" group: */
2199 s->opt[OPT_MODE_GROUP].title = "Scan Mode";
2200 s->opt[OPT_MODE_GROUP].desc = "";
2201 s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
2202 s->opt[OPT_MODE_GROUP].cap = 0;
2203 s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2204
2205 /* scan mode */
2206 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
2207 s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
2208 s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
2209 s->opt[OPT_MODE].type = SANE_TYPE_STRING;
2210 s->opt[OPT_MODE].size = max_string_size (mode_list);
2211 s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2212 s->opt[OPT_MODE].constraint.string_list = mode_list;
2213 s->val[OPT_MODE].s = strdup (mode_list[3]);
2214
2215 /* horizontal resolution */
2216 s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2217 s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2218 s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2219 s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT;
2220 s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI;
2221 s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2222 s->opt[OPT_X_RESOLUTION].constraint.word_list = s->hw->horz_resolution_list;
2223 s->val[OPT_X_RESOLUTION].w = 100;
2224
2225 /* vertical resolution */
2226 s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION;
2227 s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION;
2228 s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION;
2229 s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT;
2230 s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI;
2231 s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2232 s->opt[OPT_Y_RESOLUTION].constraint.word_list = s->hw->vert_resolution_list;
2233 s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE;
2234 s->val[OPT_Y_RESOLUTION].w = 100;
2235
2236 /* bind resolution */
2237 s->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND;
2238 s->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND;
2239 s->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND;
2240 s->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL;
2241 s->val[OPT_RESOLUTION_BIND].w = SANE_TRUE;
2242
2243 if (!(s->hw->flags & ARTEC_FLAG_SEPARATE_RES))
2244 s->opt[OPT_RESOLUTION_BIND].cap |= SANE_CAP_INACTIVE;
2245
2246 /* Preview Mode */
2247 s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
2248 s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2249 s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
2250 s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
2251 s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE;
2252 s->opt[OPT_PREVIEW].size = sizeof (SANE_Word);
2253 s->val[OPT_PREVIEW].w = SANE_FALSE;
2254
2255 /* Grayscale Preview Mode */
2256 s->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW;
2257 s->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW;
2258 s->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW;
2259 s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL;
2260 s->opt[OPT_GRAY_PREVIEW].unit = SANE_UNIT_NONE;
2261 s->opt[OPT_GRAY_PREVIEW].size = sizeof (SANE_Word);
2262 s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE;
2263
2264 /* negative */
2265 s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
2266 s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
2267 s->opt[OPT_NEGATIVE].desc = "Negative Image";
2268 s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
2269 s->val[OPT_NEGATIVE].w = SANE_FALSE;
2270
2271 if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE))
2272 {
2273 s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
2274 }
2275
2276 /* "Geometry" group: */
2277 s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
2278 s->opt[OPT_GEOMETRY_GROUP].desc = "";
2279 s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2280 s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
2281 s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2282
2283 /* top-left x */
2284 s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2285 s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2286 s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2287 s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2288 s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2289
2290 s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2291 s->opt[OPT_TL_X].constraint.range = &s->hw->x_range;
2292 s->val[OPT_TL_X].w = s->hw->x_range.min;
2293
2294 /* top-left y */
2295 s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2296 s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2297 s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2298 s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2299 s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2300
2301 s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2302 s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range;
2303 s->val[OPT_TL_Y].w = s->hw->y_range.min;
2304
2305 /* bottom-right x */
2306 s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2307 s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2308 s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2309 s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2310 s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2311
2312 s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2313 s->opt[OPT_BR_X].constraint.range = &s->hw->x_range;
2314 s->val[OPT_BR_X].w = s->hw->x_range.max;
2315
2316 /* bottom-right y */
2317 s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2318 s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2319 s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2320 s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2321 s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2322
2323 s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2324 s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range;
2325 s->val[OPT_BR_Y].w = s->hw->y_range.max;
2326
2327 /* Enhancement group: */
2328 s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
2329 s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
2330 s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
2331 s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
2332 s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2333
2334 /* filter mode */
2335 s->opt[OPT_FILTER_TYPE].name = "filter-type";
2336 s->opt[OPT_FILTER_TYPE].title = "Filter Type";
2337 s->opt[OPT_FILTER_TYPE].desc = "Filter Type for mono scans";
2338 s->opt[OPT_FILTER_TYPE].type = SANE_TYPE_STRING;
2339 s->opt[OPT_FILTER_TYPE].size = max_string_size (filter_type_list);
2340 s->opt[OPT_FILTER_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2341 s->opt[OPT_FILTER_TYPE].constraint.string_list = filter_type_list;
2342 s->val[OPT_FILTER_TYPE].s = strdup (filter_type_list[0]);
2343 s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE;
2344
2345 /* contrast */
2346 s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
2347 s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
2348 s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
2349 s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
2350 s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
2351 s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2352 s->opt[OPT_CONTRAST].constraint.range = &s->hw->brightness_range;
2353 s->val[OPT_CONTRAST].w = 0x80;
2354
2355 if (!(s->hw->flags & ARTEC_FLAG_OPT_CONTRAST))
2356 {
2357 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
2358 }
2359
2360 /* brightness */
2361 s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
2362 s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
2363 s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2364 s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
2365 s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
2366 s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2367 s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->contrast_range;
2368 s->val[OPT_BRIGHTNESS].w = 0x80;
2369
2370 if (!(s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS))
2371 {
2372 s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2373 }
2374
2375 /* threshold */
2376 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
2377 s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
2378 s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
2379 s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
2380 s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
2381 s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
2382 s->opt[OPT_THRESHOLD].constraint.range = &s->hw->threshold_range;
2383 s->val[OPT_THRESHOLD].w = 0x80;
2384 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2385
2386 /* halftone pattern */
2387 s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
2388 s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
2389 s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
2390 s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
2391 s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list);
2392 s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2393 s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list;
2394 s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[1]);
2395 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
2396
2397 /* pixel averaging */
2398 s->opt[OPT_PIXEL_AVG].name = "pixel-avg";
2399 s->opt[OPT_PIXEL_AVG].title = "Pixel Averaging";
2400 s->opt[OPT_PIXEL_AVG].desc = "Enable HardWare Pixel Averaging function";
2401 s->opt[OPT_PIXEL_AVG].type = SANE_TYPE_BOOL;
2402 s->val[OPT_PIXEL_AVG].w = SANE_FALSE;
2403
2404 if (!(s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING))
2405 {
2406 s->opt[OPT_PIXEL_AVG].cap |= SANE_CAP_INACTIVE;
2407 }
2408
2409 /* lineart line edge enhancement */
2410 s->opt[OPT_EDGE_ENH].name = "edge-enh";
2411 s->opt[OPT_EDGE_ENH].title = "Line Edge Enhancement";
2412 s->opt[OPT_EDGE_ENH].desc = "Enable HardWare Lineart Line Edge Enhancement";
2413 s->opt[OPT_EDGE_ENH].type = SANE_TYPE_BOOL;
2414 s->val[OPT_EDGE_ENH].w = SANE_FALSE;
2415 s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE;
2416
2417 /* custom-gamma table */
2418 s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
2419 s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
2420 s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
2421 s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
2422 s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE;
2423
2424 /* grayscale gamma vector */
2425 s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
2426 s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
2427 s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
2428 s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
2429 s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
2430 s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
2431 s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]);
2432 s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range;
2433 s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof (SANE_Word);
2434
2435 /* red gamma vector */
2436 s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
2437 s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
2438 s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
2439 s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
2440 s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
2441 s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
2442 s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]);
2443 s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range);
2444 s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof (SANE_Word);
2445
2446 /* green gamma vector */
2447 s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
2448 s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
2449 s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
2450 s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
2451 s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
2452 s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
2453 s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]);
2454 s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range);
2455 s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof (SANE_Word);
2456
2457 /* blue gamma vector */
2458 s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
2459 s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
2460 s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
2461 s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
2462 s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
2463 s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
2464 s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]);
2465 s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range);
2466 s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof (SANE_Word);
2467
2468 if (s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE)
2469 {
2470 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
2471 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
2472 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
2473 }
2474
2475 if (!(s->hw->flags & ARTEC_FLAG_GAMMA))
2476 {
2477 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
2478 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
2479 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
2480 s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
2481 s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
2482 }
2483
2484 /* transparency */
2485 s->opt[OPT_TRANSPARENCY].name = "transparency";
2486 s->opt[OPT_TRANSPARENCY].title = "Transparency";
2487 s->opt[OPT_TRANSPARENCY].desc = "Use transparency adaptor";
2488 s->opt[OPT_TRANSPARENCY].type = SANE_TYPE_BOOL;
2489 s->val[OPT_TRANSPARENCY].w = SANE_FALSE;
2490
2491 /* ADF */
2492 s->opt[OPT_ADF].name = "adf";
2493 s->opt[OPT_ADF].title = "ADF";
2494 s->opt[OPT_ADF].desc = "Use ADF";
2495 s->opt[OPT_ADF].type = SANE_TYPE_BOOL;
2496 s->val[OPT_ADF].w = SANE_FALSE;
2497
2498 /* Calibration group: */
2499 s->opt[OPT_CALIBRATION_GROUP].title = "Calibration";
2500 s->opt[OPT_CALIBRATION_GROUP].desc = "";
2501 s->opt[OPT_CALIBRATION_GROUP].type = SANE_TYPE_GROUP;
2502 s->opt[OPT_CALIBRATION_GROUP].cap = SANE_CAP_ADVANCED;
2503 s->opt[OPT_CALIBRATION_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2504
2505 /* Calibrate Every Scan? */
2506 s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL;
2507 s->opt[OPT_QUALITY_CAL].title = "Hardware Calibrate Every Scan";
2508 s->opt[OPT_QUALITY_CAL].desc = "Perform hardware calibration on every scan";
2509 s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL;
2510 s->val[OPT_QUALITY_CAL].w = SANE_FALSE;
2511
2512 if (!(s->hw->flags & ARTEC_FLAG_CALIBRATE))
2513 {
2514 s->opt[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE;
2515 }
2516
2517 /* Perform Software Quality Calibration */
2518 s->opt[OPT_SOFTWARE_CAL].name = "software-cal";
2519 s->opt[OPT_SOFTWARE_CAL].title = "Software Color Calibration";
2520 s->opt[OPT_SOFTWARE_CAL].desc = "Perform software quality calibration in "
2521 "addition to hardware calibration";
2522 s->opt[OPT_SOFTWARE_CAL].type = SANE_TYPE_BOOL;
2523 s->val[OPT_SOFTWARE_CAL].w = SANE_FALSE;
2524
2525 /* check for RGB calibration now because we have only implemented software */
2526 /* calibration in conjunction with hardware RGB calibration */
2527 if ((!(s->hw->flags & ARTEC_FLAG_CALIBRATE)) ||
2528 (!(s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB)))
2529 {
2530 s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE;
2531 }
2532
2533 return (SANE_STATUS_GOOD);
2534 }
2535
2536 static SANE_Status
do_cancel(ARTEC_Scanner * s)2537 do_cancel (ARTEC_Scanner * s)
2538 {
2539 DBG (7, "do_cancel()\n");
2540
2541 s->scanning = SANE_FALSE;
2542
2543 /* DAL: Terminate a three pass scan properly */
2544 /* if (s->this_pass == 3) */
2545 s->this_pass = 0;
2546
2547 if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) &&
2548 (tmp_line_buf != NULL))
2549 {
2550 artec_buffer_line_offset_free ();
2551 }
2552
2553 if (s->fd >= 0)
2554 {
2555 sanei_scsi_close (s->fd);
2556 s->fd = -1;
2557 }
2558
2559 return (SANE_STATUS_CANCELLED);
2560 }
2561
2562
2563 static SANE_Status
attach_one(const char *dev)2564 attach_one (const char *dev)
2565 {
2566 DBG (7, "attach_one()\n");
2567
2568 attach (dev, 0);
2569 return (SANE_STATUS_GOOD);
2570 }
2571
2572
2573 SANE_Status
sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize)2574 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
2575 {
2576 char dev_name[PATH_MAX], *cp;
2577 size_t len;
2578 FILE *fp;
2579
2580 DBG_INIT ();
2581
2582 DBG (1, "Artec/Ultima backend version %d.%d.%d, last mod: %s\n",
2583 ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB, ARTEC_LAST_MOD);
2584 DBG (1, "http://www4.infi.net/~cpinkham/sane-artec-doc.html\n");
2585
2586 DBG (7, "sane_init()\n" );
2587
2588 devlist = 0;
2589 /* make sure these 2 are empty */
2590 strcpy (artec_vendor, "");
2591 strcpy (artec_model, "");
2592
2593 if (version_code)
2594 *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, 0);
2595
2596 if (authorize)
2597 DBG (7, "sane_init(), authorize %s null\n", (authorize) ? "!=" : "==");
2598
2599 fp = sanei_config_open (ARTEC_CONFIG_FILE);
2600 if (!fp)
2601 {
2602 /* default to /dev/scanner instead of insisting on config file */
2603 attach ("/dev/scanner", 0);
2604 return (SANE_STATUS_GOOD);
2605 }
2606
2607 while (sanei_config_read (dev_name, sizeof (dev_name), fp))
2608 {
2609 cp = artec_skip_whitespace (dev_name);
2610
2611 /* ignore line comments and blank lines */
2612 if ((!*cp) || (*cp == '#'))
2613 continue;
2614
2615 len = strlen (cp);
2616
2617 /* ignore empty lines */
2618 if (!len)
2619 continue;
2620
2621 DBG (50, "%s line: '%s', len = %lu\n", ARTEC_CONFIG_FILE, cp,
2622 (u_long) len);
2623
2624 /* check to see if they forced a vendor string in artec.conf */
2625 if ((strncmp (cp, "vendor", 6) == 0) && isspace (cp[6]))
2626 {
2627 cp += 7;
2628 cp = artec_skip_whitespace (cp);
2629
2630 strcpy (artec_vendor, cp);
2631 DBG (5, "sane_init: Forced vendor string '%s' in %s.\n",
2632 cp, ARTEC_CONFIG_FILE);
2633 }
2634 /* OK, maybe they forced the model string in artec.conf */
2635 else if ((strncmp (cp, "model", 5) == 0) && isspace (cp[5]))
2636 {
2637 cp += 6;
2638 cp = artec_skip_whitespace (cp);
2639
2640 strcpy (artec_model, cp);
2641 DBG (5, "sane_init: Forced model string '%s' in %s.\n",
2642 cp, ARTEC_CONFIG_FILE);
2643 }
2644 /* well, nothing else to do but attempt the attach */
2645 else
2646 {
2647 sanei_config_attach_matching_devices (dev_name, attach_one);
2648 strcpy (artec_vendor, "");
2649 strcpy (artec_model, "");
2650 }
2651 }
2652 fclose (fp);
2653
2654 return (SANE_STATUS_GOOD);
2655 }
2656
2657 void
sane_exit(void)2658 sane_exit (void)
2659 {
2660 ARTEC_Device *dev, *next;
2661
2662 DBG (7, "sane_exit()\n");
2663
2664 for (dev = first_dev; dev; dev = next)
2665 {
2666 next = dev->next;
2667 free ((void *) dev->sane.name);
2668 free ((void *) dev->sane.model);
2669 free (dev);
2670 }
2671
2672 if (devlist)
2673 free (devlist);
2674 }
2675
2676 SANE_Status
sane_get_devices(const SANE_Device *** device_list, SANE_Bool local_only)2677 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
2678 {
2679 ARTEC_Device *dev;
2680 int i;
2681
2682 DBG (7, "sane_get_devices( device_list, local_only = %d )\n", local_only );
2683
2684 if (devlist)
2685 free (devlist);
2686
2687 devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
2688 if (!devlist)
2689 return SANE_STATUS_NO_MEM;
2690
2691 i = 0;
2692 for (dev = first_dev; i < num_devices; dev = dev->next)
2693 devlist[i++] = &dev->sane;
2694 devlist[i++] = 0;
2695
2696 *device_list = devlist;
2697
2698 return (SANE_STATUS_GOOD);
2699 }
2700
2701 SANE_Status
sane_open(SANE_String_Const devicename, SANE_Handle * handle)2702 sane_open (SANE_String_Const devicename, SANE_Handle * handle)
2703 {
2704 SANE_Status status;
2705 ARTEC_Device *dev;
2706 ARTEC_Scanner *s;
2707 int i, j;
2708
2709 DBG (7, "sane_open()\n");
2710
2711 if (devicename[0])
2712 {
2713 for (dev = first_dev; dev; dev = dev->next)
2714 if (strcmp (dev->sane.name, devicename) == 0)
2715 break;
2716
2717 if (!dev)
2718 {
2719 status = attach (devicename, &dev);
2720 if (status != SANE_STATUS_GOOD)
2721 return (status);
2722 }
2723 }
2724 else
2725 {
2726 /* empty devicname -> use first device */
2727 dev = first_dev;
2728 }
2729
2730 if (!dev)
2731 return SANE_STATUS_INVAL;
2732
2733 s = malloc (sizeof (*s));
2734 if (!s)
2735 return SANE_STATUS_NO_MEM;
2736 memset (s, 0, sizeof (*s));
2737 s->fd = -1;
2738 s->hw = dev;
2739 s->this_pass = 0;
2740
2741 s->gamma_length = s->hw->gamma_length;
2742 s->gamma_range.min = 0;
2743 s->gamma_range.max = s->gamma_length - 1;
2744 s->gamma_range.quant = 0;
2745
2746 /* not sure if I need this or not, it was in the umax backend though. :-) */
2747 for (j = 0; j < s->gamma_length; ++j)
2748 {
2749 s->gamma_table[0][j] = j * (s->gamma_length - 1) / s->gamma_length;
2750 }
2751
2752 for (i = 1; i < 4; i++)
2753 {
2754 for (j = 0; j < s->gamma_length; ++j)
2755 {
2756 s->gamma_table[i][j] = j;
2757 }
2758 }
2759
2760 init_options (s);
2761
2762 /* insert newly opened handle into list of open handles: */
2763 s->next = first_handle;
2764 first_handle = s;
2765
2766 *handle = s;
2767
2768 if (s->hw->flags & ARTEC_FLAG_CALIBRATE)
2769 {
2770 status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
2771
2772 if (status != SANE_STATUS_GOOD)
2773 {
2774 DBG (1, "error opening scanner for initial calibration: %s\n",
2775 sane_strstatus (status));
2776 s->fd = -1;
2777 return status;
2778 }
2779
2780 status = artec_calibrate_shading (s);
2781
2782 if (status != SANE_STATUS_GOOD)
2783 {
2784 DBG (1, "initial shading calibration failed: %s\n",
2785 sane_strstatus (status));
2786 sanei_scsi_close (s->fd);
2787 s->fd = -1;
2788 return status;
2789 }
2790
2791 sanei_scsi_close (s->fd);
2792 }
2793
2794 return (SANE_STATUS_GOOD);
2795 }
2796
2797 void
sane_close(SANE_Handle handle)2798 sane_close (SANE_Handle handle)
2799 {
2800 ARTEC_Scanner *prev, *s;
2801
2802 DBG (7, "sane_close()\n");
2803
2804 if ((DBG_LEVEL == 101) &&
2805 (debug_fd > -1))
2806 {
2807 close (debug_fd);
2808 DBG (101, "closed artec.data.raw output file\n");
2809 }
2810
2811 /* remove handle from list of open handles: */
2812 prev = 0;
2813 for (s = first_handle; s; s = s->next)
2814 {
2815 if (s == handle)
2816 break;
2817 prev = s;
2818 }
2819 if (!s)
2820 {
2821 DBG (1, "close: invalid handle %p\n", handle);
2822 return; /* oops, not a handle we know about */
2823 }
2824
2825 if (s->scanning)
2826 do_cancel (handle);
2827
2828
2829 if (prev)
2830 prev->next = s->next;
2831 else
2832 first_handle = s->next;
2833
2834 free (handle);
2835 }
2836
2837 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)2838 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
2839 {
2840 ARTEC_Scanner *s = handle;
2841
2842 DBG (7, "sane_get_option_descriptor()\n");
2843
2844 if (((unsigned) option >= NUM_OPTIONS) ||
2845 (option < 0 ))
2846 return (0);
2847
2848 return (s->opt + option);
2849 }
2850
2851 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info)2852 sane_control_option (SANE_Handle handle, SANE_Int option,
2853 SANE_Action action, void *val, SANE_Int * info)
2854 {
2855 ARTEC_Scanner *s = handle;
2856 SANE_Status status;
2857 SANE_Word w, cap;
2858
2859 DBG (7, "sane_control_option()\n");
2860
2861 if (info)
2862 *info = 0;
2863
2864 if (s->scanning)
2865 return SANE_STATUS_DEVICE_BUSY;
2866
2867 if (s->this_pass)
2868 return SANE_STATUS_DEVICE_BUSY;
2869
2870 if (option >= NUM_OPTIONS)
2871 return SANE_STATUS_INVAL;
2872
2873 cap = s->opt[option].cap;
2874
2875 if (!SANE_OPTION_IS_ACTIVE (cap))
2876 return SANE_STATUS_INVAL;
2877
2878 if (action == SANE_ACTION_GET_VALUE)
2879 {
2880 DBG (13, "sane_control_option %d, get value\n", option);
2881
2882 switch (option)
2883 {
2884 /* word options: */
2885 case OPT_X_RESOLUTION:
2886 case OPT_Y_RESOLUTION:
2887 case OPT_PREVIEW:
2888 case OPT_GRAY_PREVIEW:
2889 case OPT_RESOLUTION_BIND:
2890 case OPT_NEGATIVE:
2891 case OPT_TRANSPARENCY:
2892 case OPT_ADF:
2893 case OPT_TL_X:
2894 case OPT_TL_Y:
2895 case OPT_BR_X:
2896 case OPT_BR_Y:
2897 case OPT_NUM_OPTS:
2898 case OPT_QUALITY_CAL:
2899 case OPT_SOFTWARE_CAL:
2900 case OPT_CONTRAST:
2901 case OPT_BRIGHTNESS:
2902 case OPT_THRESHOLD:
2903 case OPT_CUSTOM_GAMMA:
2904 case OPT_PIXEL_AVG:
2905 case OPT_EDGE_ENH:
2906 *(SANE_Word *) val = s->val[option].w;
2907 return (SANE_STATUS_GOOD);
2908
2909 /* string options: */
2910 case OPT_MODE:
2911 case OPT_FILTER_TYPE:
2912 case OPT_HALFTONE_PATTERN:
2913 strcpy (val, s->val[option].s);
2914 return (SANE_STATUS_GOOD);
2915
2916 /* word array options: */
2917 case OPT_GAMMA_VECTOR:
2918 case OPT_GAMMA_VECTOR_R:
2919 case OPT_GAMMA_VECTOR_G:
2920 case OPT_GAMMA_VECTOR_B:
2921 memcpy (val, s->val[option].wa, s->opt[option].size);
2922 return (SANE_STATUS_GOOD);
2923 }
2924 }
2925 else if (action == SANE_ACTION_SET_VALUE)
2926 {
2927 DBG (13, "sane_control_option %d, set value\n", option);
2928
2929 if (!SANE_OPTION_IS_SETTABLE (cap))
2930 return (SANE_STATUS_INVAL);
2931
2932 status = sanei_constrain_value (s->opt + option, val, info);
2933 if (status != SANE_STATUS_GOOD)
2934 return (status);
2935
2936 switch (option)
2937 {
2938 /* (mostly) side-effect-free word options: */
2939 case OPT_X_RESOLUTION:
2940 case OPT_Y_RESOLUTION:
2941 case OPT_BR_X:
2942 case OPT_BR_Y:
2943 case OPT_TL_X:
2944 case OPT_TL_Y:
2945 if (info && s->val[option].w != *(SANE_Word *) val)
2946 *info |= SANE_INFO_RELOAD_PARAMS;
2947
2948 /* fall through */
2949 case OPT_PREVIEW:
2950 case OPT_GRAY_PREVIEW:
2951 case OPT_QUALITY_CAL:
2952 case OPT_SOFTWARE_CAL:
2953 case OPT_NUM_OPTS:
2954 case OPT_NEGATIVE:
2955 case OPT_TRANSPARENCY:
2956 case OPT_ADF:
2957 case OPT_CONTRAST:
2958 case OPT_BRIGHTNESS:
2959 case OPT_THRESHOLD:
2960 case OPT_PIXEL_AVG:
2961 case OPT_EDGE_ENH:
2962 s->val[option].w = *(SANE_Word *) val;
2963 return (SANE_STATUS_GOOD);
2964
2965 case OPT_MODE:
2966 {
2967 if (s->val[option].s)
2968 free (s->val[option].s);
2969
2970 s->val[option].s = (SANE_Char *) strdup (val);
2971
2972 if (info)
2973 *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
2974
2975 s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE;
2976
2977 /* options INvisible by default */
2978 s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
2979 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
2980 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
2981 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
2982 s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2983 s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
2984 s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE;
2985 s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE;
2986
2987 /* options VISIBLE by default */
2988 s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
2989 s->opt[OPT_FILTER_TYPE].cap &= ~SANE_CAP_INACTIVE;
2990 s->opt[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE;
2991
2992 if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)
2993 {
2994 /* Lineart mode */
2995 s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; /* OFF */
2996 s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
2997
2998 if (s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE)
2999 s->opt[OPT_EDGE_ENH].cap &= ~SANE_CAP_INACTIVE;
3000 }
3001 else if (strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)
3002 {
3003 /* Halftone mode */
3004 if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN)
3005 s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
3006 }
3007 else if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0)
3008 {
3009 /* Grayscale mode */
3010 if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE))
3011 {
3012 s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
3013 }
3014 }
3015 else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0)
3016 {
3017 /* Color mode */
3018 s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE;
3019 s->opt[OPT_SOFTWARE_CAL].cap &= ~SANE_CAP_INACTIVE;
3020 if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE))
3021 {
3022 s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
3023 }
3024 }
3025 }
3026 return (SANE_STATUS_GOOD);
3027
3028 case OPT_FILTER_TYPE:
3029 case OPT_HALFTONE_PATTERN:
3030 if (s->val[option].s)
3031 free (s->val[option].s);
3032 s->val[option].s = strdup (val);
3033 return (SANE_STATUS_GOOD);
3034
3035 case OPT_RESOLUTION_BIND:
3036 if (s->val[option].w != *(SANE_Word *) val)
3037 {
3038 s->val[option].w = *(SANE_Word *) val;
3039
3040 if (info)
3041 {
3042 *info |= SANE_INFO_RELOAD_OPTIONS;
3043 }
3044
3045 if (s->val[option].w == SANE_FALSE)
3046 { /* don't bind */
3047 s->opt[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE;
3048 s->opt[OPT_X_RESOLUTION].title =
3049 SANE_TITLE_SCAN_X_RESOLUTION;
3050 s->opt[OPT_X_RESOLUTION].name =
3051 SANE_NAME_SCAN_RESOLUTION;
3052 s->opt[OPT_X_RESOLUTION].desc =
3053 SANE_DESC_SCAN_X_RESOLUTION;
3054 }
3055 else
3056 { /* bind */
3057 s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE;
3058 s->opt[OPT_X_RESOLUTION].title =
3059 SANE_TITLE_SCAN_RESOLUTION;
3060 s->opt[OPT_X_RESOLUTION].name =
3061 SANE_NAME_SCAN_RESOLUTION;
3062 s->opt[OPT_X_RESOLUTION].desc =
3063 SANE_DESC_SCAN_RESOLUTION;
3064 }
3065 }
3066 return (SANE_STATUS_GOOD);
3067
3068 /* side-effect-free word-array options: */
3069 case OPT_GAMMA_VECTOR:
3070 case OPT_GAMMA_VECTOR_R:
3071 case OPT_GAMMA_VECTOR_G:
3072 case OPT_GAMMA_VECTOR_B:
3073 memcpy (s->val[option].wa, val, s->opt[option].size);
3074 return (SANE_STATUS_GOOD);
3075
3076 /* options with side effects: */
3077 case OPT_CUSTOM_GAMMA:
3078 w = *(SANE_Word *) val;
3079 if (w == s->val[OPT_CUSTOM_GAMMA].w)
3080 return (SANE_STATUS_GOOD);
3081
3082 s->val[OPT_CUSTOM_GAMMA].w = w;
3083 if (w) /* use custom_gamma_table */
3084 {
3085 const char *mode = s->val[OPT_MODE].s;
3086
3087 if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) ||
3088 (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) ||
3089 (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0))
3090 {
3091 s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
3092 }
3093 else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)
3094 {
3095 s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
3096
3097 if (!(s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE))
3098 {
3099 s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
3100 s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
3101 s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
3102 }
3103 }
3104 }
3105 else
3106 /* don't use custom_gamma_table */
3107 {
3108 s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
3109 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
3110 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
3111 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
3112 }
3113
3114 if (info)
3115 *info |= SANE_INFO_RELOAD_OPTIONS;
3116
3117 return (SANE_STATUS_GOOD);
3118 }
3119 }
3120
3121 return (SANE_STATUS_INVAL);
3122 }
3123
3124 static void
set_pass_parameters(SANE_Handle handle)3125 set_pass_parameters (SANE_Handle handle)
3126 {
3127 ARTEC_Scanner *s = handle;
3128
3129 DBG (7, "set_pass_parameters()\n");
3130
3131 if (s->threepasscolor)
3132 {
3133 s->this_pass += 1;
3134 DBG (9, "set_pass_parameters: three-pass, on %d\n", s->this_pass);
3135 switch (s->this_pass)
3136 {
3137 case 1:
3138 s->params.format = SANE_FRAME_RED;
3139 s->params.last_frame = SANE_FALSE;
3140 break;
3141 case 2:
3142 s->params.format = SANE_FRAME_GREEN;
3143 s->params.last_frame = SANE_FALSE;
3144 break;
3145 case 3:
3146 s->params.format = SANE_FRAME_BLUE;
3147 s->params.last_frame = SANE_TRUE;
3148 break;
3149 default:
3150 DBG (9, "set_pass_parameters: What?!? pass %d = filter?\n",
3151 s->this_pass);
3152 break;
3153 }
3154 }
3155 else
3156 s->this_pass = 0;
3157 }
3158
3159 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters * params)3160 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
3161 {
3162 ARTEC_Scanner *s = handle;
3163
3164 DBG (7, "sane_get_parameters()\n");
3165
3166 if (!s->scanning)
3167 {
3168 double width, height;
3169
3170 memset (&s->params, 0, sizeof (s->params));
3171
3172 s->x_resolution = s->val[OPT_X_RESOLUTION].w;
3173 s->y_resolution = s->val[OPT_Y_RESOLUTION].w;
3174
3175 if ((s->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) ||
3176 (s->val[OPT_PREVIEW].w == SANE_TRUE))
3177 {
3178 s->y_resolution = s->x_resolution;
3179 }
3180
3181 s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH
3182 * s->x_resolution;
3183 s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH
3184 * s->y_resolution;
3185 width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w);
3186 height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w);
3187
3188 if ((s->x_resolution > 0.0) &&
3189 (s->y_resolution > 0.0) &&
3190 (width > 0.0) &&
3191 (height > 0.0))
3192 {
3193 s->params.pixels_per_line = width * s->x_resolution / MM_PER_INCH + 1;
3194 s->params.lines = height * s->y_resolution / MM_PER_INCH + 1;
3195 }
3196
3197 s->onepasscolor = SANE_FALSE;
3198 s->threepasscolor = SANE_FALSE;
3199 s->params.last_frame = SANE_TRUE;
3200
3201 if ((s->val[OPT_PREVIEW].w == SANE_TRUE) &&
3202 (s->val[OPT_GRAY_PREVIEW].w == SANE_TRUE))
3203 {
3204 s->mode = SANE_VALUE_SCAN_MODE_GRAY;
3205 }
3206 else
3207 {
3208 s->mode = s->val[OPT_MODE].s;
3209 }
3210
3211 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) ||
3212 (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0))
3213 {
3214 s->params.format = SANE_FRAME_GRAY;
3215 s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
3216 s->params.depth = 1;
3217 s->line_offset = 0;
3218
3219 /* round pixels_per_line up to the next full byte of pixels */
3220 /* this way we don't have to do bit buffering, pixels_per_line is */
3221 /* what is used in the set window command. */
3222 /* SANE expects the last byte in a line to be padded if it's not */
3223 /* full, so this should not affect scans in a negative way */
3224 s->params.pixels_per_line = s->params.bytes_per_line * 8;
3225 }
3226 else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)
3227 {
3228 s->params.format = SANE_FRAME_GRAY;
3229 s->params.bytes_per_line = s->params.pixels_per_line;
3230 s->params.depth = 8;
3231 s->line_offset = 0;
3232 }
3233 else
3234 {
3235 s->params.bytes_per_line = s->params.pixels_per_line;
3236 s->params.depth = 8;
3237
3238 if (s->hw->flags & ARTEC_FLAG_ONE_PASS_SCANNER)
3239 {
3240 s->onepasscolor = SANE_TRUE;
3241 s->params.format = SANE_FRAME_RGB;
3242 s->params.bytes_per_line *= 3;
3243
3244 /*
3245 * line offsets from documentation.
3246 * (I don't yet see a common formula I can easily use)
3247 */
3248 /* FIXME: figure out a cleaner way to do this... */
3249 s->line_offset = 0; /* default */
3250 if ((!strcmp (s->hw->sane.model, "AT3")) ||
3251 (!strcmp (s->hw->sane.model, "A6000C")) ||
3252 (!strcmp (s->hw->sane.model, "A6000C PLUS")) ||
3253 (!strcmp (s->hw->sane.model, "AT6")))
3254 {
3255 /* formula #1 */
3256 /* ranges from 1 at 50dpi to 16 at 600dpi */
3257 s->line_offset = 8 * (s->y_resolution / 300.0);
3258 }
3259 else if (!strcmp (s->hw->sane.model, "AT12"))
3260 {
3261 /* formula #2 */
3262 /* ranges from 0 at 25dpi to 16 at 1200dpi */
3263 /***********************************************************/
3264 /* this should be handled in hardware for now, so leave it */
3265 /* sitting at zero for now. */
3266 /***********************************************************/
3267 /*
3268 s->line_offset = 16 * ( s->y_resolution / 1200.0 );
3269 */
3270 }
3271 else if (!strcmp (s->hw->sane.model, "AM12S"))
3272 {
3273 /* formula #3 */
3274 /* ranges from 0 at 50dpi to 8 at 1200dpi */
3275 s->line_offset = 8 * (s->y_resolution / 1200.0);
3276 }
3277 }
3278 else
3279 {
3280 s->params.last_frame = SANE_FALSE;
3281 s->threepasscolor = SANE_TRUE;
3282 s->line_offset = 0;
3283 }
3284 }
3285 }
3286
3287 if (params)
3288 *params = s->params;
3289
3290 return (SANE_STATUS_GOOD);
3291 }
3292
3293
3294 SANE_Status
sane_start(SANE_Handle handle)3295 sane_start (SANE_Handle handle)
3296 {
3297 ARTEC_Scanner *s = handle;
3298 SANE_Status status;
3299
3300 DBG (7, "sane_start()\n");
3301
3302 if (debug_fd != -1)
3303 {
3304 close (debug_fd);
3305 debug_fd = -1;
3306 }
3307
3308 if (DBG_LEVEL == 101)
3309 {
3310 debug_fd = open ("artec.data.raw",
3311 O_WRONLY | O_CREAT | O_TRUNC, 0666);
3312 if (debug_fd > -1)
3313 DBG (101, "opened artec.data.raw output file\n");
3314 }
3315
3316 /* First make sure we have a current parameter set. Some of the */
3317 /* parameters will be overwritten below, but that's OK. */
3318 status = sane_get_parameters (s, 0);
3319 if (status != SANE_STATUS_GOOD)
3320 return status;
3321
3322 /* DAL: For 3 pass colour set the current pass parameters */
3323 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && s->threepasscolor)
3324 set_pass_parameters (s);
3325
3326 /* DAL: For single pass scans and the first pass of a 3 pass scan */
3327 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) ||
3328 (!s->threepasscolor) ||
3329 ((s->threepasscolor) &&
3330 (s->this_pass == 1)))
3331 {
3332
3333 if (s->hw->flags & ARTEC_FLAG_SENSE_HANDLER)
3334 {
3335 status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler,
3336 (void *)s);
3337 }
3338 else
3339 {
3340 status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0);
3341 }
3342
3343 if (status != SANE_STATUS_GOOD)
3344 {
3345 DBG (1, "open of %s failed: %s\n",
3346 s->hw->sane.name, sane_strstatus (status));
3347 return status;
3348 }
3349
3350 /* DB added wait_ready */
3351 status = wait_ready (s->fd);
3352 if (status != SANE_STATUS_GOOD)
3353 {
3354 DBG (1, "wait for scanner ready failed: %s\n",
3355 sane_strstatus (status));
3356 return status;
3357 }
3358 }
3359
3360 s->bytes_to_read = s->params.bytes_per_line * s->params.lines;
3361
3362 DBG (9, "%d pixels per line, %d bytes, %d lines high, xdpi = %d, "
3363 "ydpi = %d, btr = %lu\n",
3364 s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines,
3365 s->x_resolution, s->y_resolution, (u_long) s->bytes_to_read);
3366
3367 /* DAL: For single pass scans and the first pass of a 3 pass scan */
3368 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor ||
3369 (s->threepasscolor && s->this_pass == 1))
3370 {
3371
3372 /* do a calibrate if scanner requires/recommends it */
3373 if ((s->hw->flags & ARTEC_FLAG_CALIBRATE) &&
3374 (s->val[OPT_QUALITY_CAL].w == SANE_TRUE))
3375 {
3376 status = artec_calibrate_shading (s);
3377
3378 if (status != SANE_STATUS_GOOD)
3379 {
3380 DBG (1, "shading calibration failed: %s\n",
3381 sane_strstatus (status));
3382 return status;
3383 }
3384 }
3385
3386 /* DB added wait_ready */
3387 status = wait_ready (s->fd);
3388 if (status != SANE_STATUS_GOOD)
3389 {
3390 DBG (1, "wait for scanner ready failed: %s\n",
3391 sane_strstatus (status));
3392 return status;
3393 }
3394
3395 /* send the custom gamma table if we have one */
3396 if (s->hw->flags & ARTEC_FLAG_GAMMA)
3397 artec_send_gamma_table (s);
3398
3399 /* now set our scan window */
3400 status = artec_set_scan_window (s);
3401
3402 if (status != SANE_STATUS_GOOD)
3403 {
3404 DBG (1, "set scan window failed: %s\n",
3405 sane_strstatus (status));
3406 return status;
3407 }
3408
3409 /* DB added wait_ready */
3410 status = wait_ready (s->fd);
3411 if (status != SANE_STATUS_GOOD)
3412 {
3413 DBG (1, "wait for scanner ready failed: %s\n",
3414 sane_strstatus (status));
3415 return status;
3416 }
3417 }
3418
3419 /* now we can start the actual scan */
3420 /* DAL: For single pass scans and the first pass of a 3 pass scan */
3421 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) ||
3422 (!s->threepasscolor) ||
3423 (s->this_pass == 1))
3424 {
3425 /* DAL - do mode select before each scan */
3426 /* The mode is NOT turned off at the end of the scan */
3427 artec_mode_select (s);
3428
3429 status = artec_start_scan (s);
3430
3431 if (status != SANE_STATUS_GOOD)
3432 {
3433 DBG (1, "start scan: %s\n", sane_strstatus (status));
3434 return status;
3435 }
3436 }
3437
3438 s->scanning = SANE_TRUE;
3439
3440 return (SANE_STATUS_GOOD);
3441 }
3442
3443
3444 #if 0
3445 static void
3446 binout (SANE_Byte byte)
3447 {
3448 SANE_Byte b = byte;
3449 int bit;
3450
3451 for (bit = 0; bit < 8; bit++)
3452 {
3453 DBG (9, "%d", b & 128 ? 1 : 0);
3454 b = b << 1;
3455 }
3456 }
3457 #endif
3458
3459 static SANE_Status
artec_sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)3460 artec_sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)
3461 {
3462 ARTEC_Scanner *s = handle;
3463 SANE_Status status;
3464 size_t nread;
3465 size_t lread;
3466 size_t bytes_read;
3467 size_t rows_read;
3468 size_t max_read_rows;
3469 size_t max_ret_rows;
3470 size_t remaining_rows;
3471 size_t rows_available;
3472 size_t line;
3473 SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE];
3474 SANE_Byte line_buf[ARTEC_MAX_READ_SIZE];
3475
3476
3477 DBG (7, "artec_sane_read( %p, %p, %d, %d )\n", handle, (void *) buf, max_len, *len);
3478
3479 *len = 0;
3480
3481 if (s->bytes_to_read == 0)
3482 {
3483 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor ||
3484 (s->threepasscolor && s->this_pass == 3))
3485 {
3486 do_cancel (s);
3487 /* without this a 4th pass is attempted, yet do_cancel does this */
3488 s->scanning = SANE_FALSE;
3489 }
3490 return (SANE_STATUS_EOF);
3491 }
3492
3493 if (!s->scanning)
3494 return do_cancel (s);
3495
3496 remaining_rows = (s->bytes_to_read + s->params.bytes_per_line - 1) / s->params.bytes_per_line;
3497 max_read_rows = s->hw->max_read_size / s->params.bytes_per_line;
3498 max_ret_rows = max_len / s->params.bytes_per_line;
3499
3500 while (artec_get_status (s->fd) == 0)
3501 {
3502 DBG (120, "hokey loop till data available\n");
3503 usleep (50000); /* sleep for .05 second */
3504 }
3505
3506 rows_read = 0;
3507 bytes_read = 0;
3508 while ((rows_read < max_ret_rows) && (rows_read < remaining_rows))
3509 {
3510 DBG (50, "top of while loop, rr = %lu, mrr = %lu, rem = %lu\n",
3511 (u_long) rows_read, (u_long) max_ret_rows, (u_long) remaining_rows);
3512
3513 if (s->bytes_to_read - bytes_read <= s->params.bytes_per_line * max_read_rows)
3514 {
3515 nread = s->bytes_to_read - bytes_read;
3516 }
3517 else
3518 {
3519 nread = s->params.bytes_per_line * max_read_rows;
3520 }
3521 lread = nread / s->params.bytes_per_line;
3522
3523 if ((max_read_rows - rows_read) < lread)
3524 {
3525 lread = max_read_rows - rows_read;
3526 nread = lread * s->params.bytes_per_line;
3527 }
3528
3529 if ((max_ret_rows - rows_read) < lread)
3530 {
3531 lread = max_ret_rows - rows_read;
3532 nread = lread * s->params.bytes_per_line;
3533 }
3534
3535 while ((rows_available = artec_get_status (s->fd)) == 0)
3536 {
3537 DBG (120, "hokey loop till data available\n");
3538 usleep (50000); /* sleep for .05 second */
3539 }
3540
3541 if (rows_available < lread)
3542 {
3543 lread = rows_available;
3544 nread = lread * s->params.bytes_per_line;
3545 }
3546
3547 /* This should never happen, but just in case... */
3548 if (nread > (s->bytes_to_read - bytes_read))
3549 {
3550 nread = s->bytes_to_read - bytes_read;
3551 lread = 1;
3552 }
3553
3554 DBG (50, "rows_available = %lu, params.lines = %d, bytes_per_line = %d\n",
3555 (u_long) rows_available, s->params.lines, s->params.bytes_per_line);
3556 DBG (50, "bytes_to_read = %lu, max_len = %d, max_rows = %lu\n",
3557 (u_long) s->bytes_to_read, max_len, (u_long) max_ret_rows);
3558 DBG (50, "nread = %lu, lread = %lu, bytes_read = %lu, rows_read = %lu\n",
3559 (u_long) nread, (u_long) lread, (u_long) bytes_read, (u_long) rows_read);
3560
3561 status = read_data (s->fd, ARTEC_DATA_IMAGE, temp_buf, &nread);
3562
3563 if (status != SANE_STATUS_GOOD)
3564 {
3565 end_scan (s);
3566 do_cancel (s);
3567 return (SANE_STATUS_IO_ERROR);
3568 }
3569
3570 if ((DBG_LEVEL == 101) &&
3571 (debug_fd > -1))
3572 {
3573 write (debug_fd, temp_buf, nread);
3574 }
3575
3576 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) &&
3577 (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET))
3578 {
3579 for (line = 0; line < lread; line++)
3580 {
3581 memcpy (line_buf,
3582 temp_buf + (line * s->params.bytes_per_line),
3583 s->params.bytes_per_line);
3584
3585 nread = s->params.bytes_per_line;
3586
3587 artec_buffer_line_offset (s, s->line_offset, line_buf, &nread);
3588
3589 if (nread > 0)
3590 {
3591 if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)
3592 {
3593 artec_line_rgb_to_byte_rgb (line_buf,
3594 s->params.pixels_per_line);
3595 }
3596 if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR)
3597 {
3598 artec_reverse_line (s, line_buf);
3599 }
3600
3601 /* do software calibration if necessary */
3602 if (s->val[OPT_SOFTWARE_CAL].w)
3603 {
3604 artec_software_rgb_calibrate (s, line_buf, 1);
3605 }
3606
3607 memcpy (buf + bytes_read, line_buf,
3608 s->params.bytes_per_line);
3609 bytes_read += nread;
3610 rows_read++;
3611 }
3612 }
3613 }
3614 else
3615 {
3616 if ((s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) ||
3617 ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) &&
3618 (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)))
3619 {
3620 for (line = 0; line < lread; line++)
3621 {
3622 if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) &&
3623 (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT))
3624 {
3625 artec_line_rgb_to_byte_rgb (temp_buf +
3626 (line * s->params.bytes_per_line),
3627 s->params.pixels_per_line);
3628 }
3629 if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR)
3630 {
3631 artec_reverse_line (s, temp_buf +
3632 (line * s->params.bytes_per_line));
3633 }
3634 }
3635 }
3636
3637 /* do software calibration if necessary */
3638 if ((s->val[OPT_SOFTWARE_CAL].w) &&
3639 (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0))
3640 {
3641 artec_software_rgb_calibrate (s, temp_buf, lread);
3642 }
3643
3644 memcpy (buf + bytes_read, temp_buf, nread);
3645 bytes_read += nread;
3646 rows_read += lread;
3647 }
3648 }
3649
3650 *len = bytes_read;
3651 s->bytes_to_read -= bytes_read;
3652
3653 DBG (9, "artec_sane_read() returning, we read %lu bytes, %lu left\n",
3654 (u_long) * len, (u_long) s->bytes_to_read);
3655
3656 if ((s->bytes_to_read == 0) &&
3657 (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) &&
3658 (tmp_line_buf != NULL))
3659 {
3660 artec_buffer_line_offset_free ();
3661 }
3662
3663 return (SANE_STATUS_GOOD);
3664 }
3665
3666 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)3667 sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len)
3668 {
3669 ARTEC_Scanner *s = handle;
3670 SANE_Status status;
3671 int bytes_to_copy;
3672 int loop;
3673
3674 static SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE];
3675 static int bytes_in_buf = 0;
3676
3677 DBG (7, "sane_read( %p, %p, %d, %d )\n", handle, (void *) buf, max_len, *len);
3678 DBG (9, "sane_read: bib = %d, ml = %d\n", bytes_in_buf, max_len);
3679
3680 if (bytes_in_buf != 0)
3681 {
3682 bytes_to_copy = max_len < bytes_in_buf ? max_len : bytes_in_buf;
3683 }
3684 else
3685 {
3686 status = artec_sane_read (s, temp_buf, s->hw->max_read_size, len);
3687
3688 if (status != SANE_STATUS_GOOD)
3689 {
3690 return (status);
3691 }
3692
3693 bytes_in_buf = *len;
3694
3695 if (*len == 0)
3696 {
3697 return (SANE_STATUS_GOOD);
3698 }
3699
3700 bytes_to_copy = max_len < s->hw->max_read_size ?
3701 max_len : s->hw->max_read_size;
3702 bytes_to_copy = *len < bytes_to_copy ? *len : bytes_to_copy;
3703 }
3704
3705 memcpy (buf, temp_buf, bytes_to_copy);
3706 bytes_in_buf -= bytes_to_copy;
3707 *len = bytes_to_copy;
3708
3709 DBG (9, "sane_read: btc = %d, bib now = %d\n",
3710 bytes_to_copy, bytes_in_buf);
3711
3712 for (loop = 0; loop < bytes_in_buf; loop++)
3713 {
3714 temp_buf[loop] = temp_buf[loop + bytes_to_copy];
3715 }
3716
3717 return (SANE_STATUS_GOOD);
3718 }
3719
3720 void
sane_cancel(SANE_Handle handle)3721 sane_cancel (SANE_Handle handle)
3722 {
3723 ARTEC_Scanner *s = handle;
3724
3725 DBG (7, "sane_cancel()\n");
3726
3727 if (s->scanning)
3728 {
3729 s->scanning = SANE_FALSE;
3730
3731 abort_scan (s);
3732
3733 do_cancel (s);
3734 }
3735 }
3736
3737 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)3738 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
3739 {
3740 DBG (7, "sane_set_io_mode( %p, %d )\n", handle, non_blocking);
3741
3742 return (SANE_STATUS_UNSUPPORTED);
3743 }
3744
3745 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int * fd)3746 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
3747 {
3748 DBG (7, "sane_get_select_fd( %p, %d )\n", handle, *fd );
3749
3750 return (SANE_STATUS_UNSUPPORTED);
3751 }
3752