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