xref: /third_party/backends/backend/artec.c (revision 141cc406)
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
94static int num_devices;
95static const SANE_Device **devlist = 0;
96static ARTEC_Device *first_dev;
97static ARTEC_Scanner *first_handle;
98
99static 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
108static const SANE_String_Const filter_type_list[] =
109{
110  "Mono", "Red", "Green", "Blue",
111  0
112};
113
114static 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
121static const SANE_Range u8_range =
122{
123  0,				/* minimum */
124  255,				/* maximum */
125  0				/* quantization */
126};
127
128#define INQ_LEN	0x60
129static const uint8_t inquiry[] =
130{
131  0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00
132};
133
134static const uint8_t test_unit_ready[] =
135{
136  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
137};
138
139static 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  }
152cap_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 */
274static char artec_vendor[9] = "";
275static char artec_model[17] = "";
276
277/* file descriptor for debug data output */
278static int debug_fd = -1;
279
280static char *artec_skip_whitespace (char *str)
281{
282  while (isspace (*str))
283    ++str;
284  return str;
285}
286
287static SANE_Status
288artec_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
348static size_t
349artec_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
367static size_t
368max_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 */
385static SANE_Status
386sense_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 */
618static SANE_Status
619wait_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 */
649static SANE_Status
650abort_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 */
696static SANE_Status
697artec_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
735static SANE_Status
736read_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
752static int
753artec_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
775static SANE_Status
776artec_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
829static SANE_Status
830artec_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
852static SANE_Status
853artec_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
874static SANE_Byte **line_buffer = NULL;
875static SANE_Byte *tmp_line_buf = NULL;
876static SANE_Int r_buf_lines;
877static SANE_Int g_buf_lines;
878
879static SANE_Status
880artec_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
1030static SANE_Status
1031artec_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
1052static SANE_Status
1053artec_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
1136static SANE_Status
1137artec_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
1238static SANE_Status
1239artec_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
1465static SANE_Status
1466artec_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
1492static SANE_Status
1493artec_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
1577static SANE_Status
1578artec_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
1679static SANE_Status
1680end_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
1708static SANE_Status
1709artec_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
1894static SANE_Status
1895dump_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
1929static SANE_Status
1930attach (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
2176static SANE_Status
2177init_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
2536static SANE_Status
2537do_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
2563static SANE_Status
2564attach_one (const char *dev)
2565{
2566  DBG (7, "attach_one()\n");
2567
2568  attach (dev, 0);
2569  return (SANE_STATUS_GOOD);
2570}
2571
2572
2573SANE_Status
2574sane_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
2657void
2658sane_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
2676SANE_Status
2677sane_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
2701SANE_Status
2702sane_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
2797void
2798sane_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
2837const SANE_Option_Descriptor *
2838sane_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
2851SANE_Status
2852sane_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
3124static void
3125set_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
3159SANE_Status
3160sane_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
3294SANE_Status
3295sane_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
3445static void
3446binout (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
3459static SANE_Status
3460artec_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
3666SANE_Status
3667sane_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
3720void
3721sane_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
3737SANE_Status
3738sane_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
3745SANE_Status
3746sane_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