xref: /third_party/backends/backend/bh.c (revision 141cc406)
1/* sane - Scanner Access Now Easy.
2   Copyright (C) 1999,2000 Tom Martone
3   This file is part of a SANE backend for Bell and Howell Copiscan II
4   Scanners using the Remote SCSI Controller(RSC).
5
6   This file is part of the SANE package.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
21   As a special exception, the authors of SANE give permission for
22   additional uses of the libraries contained in this release of SANE.
23
24   The exception is that, if you link a SANE library with other files
25   to produce an executable, this does not by itself cause the
26   resulting executable to be covered by the GNU General Public
27   License.  Your use of that executable is in no way restricted on
28   account of linking the SANE library code into it.
29
30   This exception does not, however, invalidate any other reasons why
31   the executable file might be covered by the GNU General Public
32   License.
33
34   If you submit changes to SANE to the maintainers to be included in
35   a subsequent release, you agree by submitting the changes that
36   those changes may be distributed with this exception intact.
37
38   If you write modifications of your own for SANE, it is your choice
39   whether to permit this exception to apply to your modifications.
40   If you do not wish that, delete this exception notice.
41
42*/
43#include "../include/sane/config.h"
44#include <limits.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <ctype.h>
48#include <stdlib.h>
49#include <string.h>
50#include <stdio.h>
51#include <unistd.h>
52#include <sys/types.h>
53#include "../include/sane/sane.h"
54#include "../include/sane/saneopts.h"
55#include "../include/sane/sanei_scsi.h"
56#include "../include/sane/sanei_config.h"
57
58#define BACKEND_NAME bh
59#include "../include/sane/sanei_backend.h"
60#define BUILD 4
61
62#include "bh.h"
63
64#define MIN(x,y) ((x)<(y) ? (x) : (y))
65#define MAX(x,y) ((x)>(y) ? (x) : (y))
66
67static const SANE_Device **devlist = 0;
68static int num_devices = 0;
69static BH_Device *first_dev = NULL;
70static BH_Scanner *first_handle = NULL;
71static SANE_Char inquiry_data[255] = "Bell+Howell scanner";
72static SANE_Int disable_optional_frames = 0;
73static SANE_Int fake_inquiry = 0;
74
75static int allblank(const char *s)
76{
77  while (s && *s)
78    if (!isspace(*s++))
79      return 0;
80
81  return 1;
82}
83
84static size_t
85max_string_size (const SANE_String_Const strings[])
86{
87  size_t size, max_size = 0;
88  int i;
89
90  for (i = 0; strings[i]; ++i)
91    {
92      size = strlen (strings[i]) + 1;
93      if (size > max_size)
94        max_size = size;
95    }
96
97  return max_size;
98}
99
100static void
101trim_spaces(char *s, size_t n)
102{
103  for (s += (n-1); n > 0; n--, s--)
104    {
105      if (*s && !isspace(*s))
106	break;
107      *s = '\0';
108    }
109}
110
111static SANE_String_Const
112print_devtype (SANE_Byte devtype)
113{
114  static SANE_String devtypes[] =
115  {
116    "disk",
117    "tape",
118    "printer",
119    "processor",
120    "CD-writer",
121    "CD-drive",
122    "scanner",
123    "optical-drive",
124    "jukebox",
125    "communicator"
126  };
127
128  return (devtype > 0 && devtype < NELEMS(devtypes)) ?
129    devtypes[devtype] :
130    "unknown-device";
131}
132
133static SANE_String_Const
134print_barcodetype (SANE_Int i)
135{
136  return (i > 0 && i < NELEMS(barcode_search_bar_list)) ?
137    barcode_search_bar_list[i] :
138    (SANE_String_Const) "unknown";
139}
140
141static SANE_String_Const
142print_orientation (SANE_Int i)
143{
144  switch(i)
145    {
146    case 0:
147    case 7:
148      return "vertical upwards";
149    case 1:
150    case 2:
151      return "horizontal right";
152    case 3:
153    case 4:
154      return "vertical downwards";
155    case 5:
156    case 6:
157      return "horizontal left";
158    default:
159      return "unknown";
160    }
161}
162
163static SANE_String_Const
164print_read_type (SANE_Int i)
165{
166  static char buf[32];
167  SANE_Int n;
168
169  /* translate BH_SCSI_READ_TYPE_ codes to a human-readable string */
170  if (i == BH_SCSI_READ_TYPE_FRONT)
171    {
172      strcpy(buf, "front page");
173    }
174  else if (i == BH_SCSI_READ_TYPE_BACK)
175    {
176      strcpy(buf, "back page");
177    }
178  else if (i > BH_SCSI_READ_TYPE_FRONT &&
179	   i <= BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS)
180    {
181      n = i - BH_SCSI_READ_TYPE_FRONT;
182      sprintf(buf, "front section %d", n);
183    }
184  else if (i > BH_SCSI_READ_TYPE_BACK &&
185	   i <= BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS)
186    {
187      n = i - BH_SCSI_READ_TYPE_BACK;
188      sprintf(buf, "back section %d", n);
189    }
190  else if (i == BH_SCSI_READ_TYPE_FRONT_BARCODE)
191    {
192      strcpy(buf, "front page barcode");
193    }
194  else if (i == BH_SCSI_READ_TYPE_BACK_BARCODE)
195    {
196      strcpy(buf, "back page barcode");
197    }
198  else if (i > BH_SCSI_READ_TYPE_FRONT_BARCODE &&
199	   i <= BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS)
200    {
201      n = i - BH_SCSI_READ_TYPE_FRONT_BARCODE;
202      sprintf(buf, "front barcode section %d", n);
203    }
204  else if (i > BH_SCSI_READ_TYPE_BACK_BARCODE &&
205	   i <= BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS)
206    {
207      n = i - BH_SCSI_READ_TYPE_BACK_BARCODE;
208      sprintf(buf, "back barcode section %d", n);
209    }
210  else if (i == BH_SCSI_READ_TYPE_FRONT_PATCHCODE)
211    {
212      strcpy(buf, "front page patchcode");
213    }
214  else if (i == BH_SCSI_READ_TYPE_BACK_PATCHCODE)
215    {
216      strcpy(buf, "back page patchcode");
217    }
218  else if (i > BH_SCSI_READ_TYPE_FRONT_PATCHCODE &&
219	   i <= BH_SCSI_READ_TYPE_FRONT_PATCHCODE + NUM_SECTIONS)
220    {
221      n = i - BH_SCSI_READ_TYPE_FRONT_PATCHCODE;
222      sprintf(buf, "front patchcode section %d", n);
223    }
224  else if (i > BH_SCSI_READ_TYPE_BACK_PATCHCODE &&
225	   i <= BH_SCSI_READ_TYPE_BACK_PATCHCODE + NUM_SECTIONS)
226    {
227      n = i - BH_SCSI_READ_TYPE_BACK_PATCHCODE;
228      sprintf(buf, "back patchcode section %d", n);
229    }
230  else if (i == BH_SCSI_READ_TYPE_FRONT_ICON)
231    {
232      strcpy(buf, "front page icon");
233    }
234  else if (i == BH_SCSI_READ_TYPE_BACK_ICON)
235    {
236      strcpy(buf, "back page icon");
237    }
238  else if (i == BH_SCSI_READ_TYPE_SENDBARFILE)
239    {
240      strcpy(buf, "transmit bar/patch codes");
241    }
242  else
243    {
244      strcpy(buf, "unknown");
245    }
246
247  return buf;
248}
249
250static SANE_Int
251get_rotation_id(char *s)
252{
253  SANE_Int i;
254
255  for (i = 0; rotation_list[i]; i++)
256    if (strcmp(s, rotation_list[i]) == 0)
257      break;
258
259  /* unknown strings are treated as '0' */
260  return rotation_list[i] ? i : 0;
261}
262
263static SANE_Int
264get_compression_id(char *s)
265{
266  SANE_Int i;
267
268  for (i = 0; compression_list[i]; i++)
269    if (strcmp(s, compression_list[i]) == 0)
270      break;
271
272  /* unknown strings are treated as 'none' */
273  return compression_list[i] ?  i : 0;
274}
275
276static SANE_Int
277get_barcode_id(char *s)
278{
279  SANE_Int i;
280
281  for (i = 0; barcode_search_bar_list[i]; i++)
282    if (strcmp(s, barcode_search_bar_list[i]) == 0)
283      break;
284
285  /* unknown strings are treated as 'none' */
286  return barcode_search_bar_list[i] ?  i : 0;
287}
288
289static SANE_Int
290get_scan_mode_id(char *s)
291{
292  SANE_Int i;
293
294  for (i = 0; scan_mode_list[i]; i++)
295    if (strcmp(s, scan_mode_list[i]) == 0)
296      break;
297
298  /* unknown strings are treated as 'lineart' */
299  return scan_mode_list[i] ?  i : 0;
300}
301
302static SANE_Int
303get_paper_id(char *s)
304{
305  SANE_Int i;
306
307  for (i = 0; paper_list[i]; i++)
308    if (strcmp(s, paper_list[i]) == 0)
309      break;
310
311  /* unknown strings are treated as 'custom' */
312  return paper_list[i] ?  i : 0;
313}
314
315static SANE_Int
316get_barcode_search_mode(char *s)
317{
318  SANE_Int i;
319
320  if (strcmp(s, "horizontal") == 0)
321    {
322      i = 1;
323    }
324  else if (strcmp(s, "vertical") == 0)
325    {
326      i = 2;
327    }
328  else if (strcmp(s, "vert-horiz") == 0)
329    {
330      i = 6;
331    }
332  else if (strcmp(s, "horiz-vert") == 0)
333    {
334      i = 9;
335    }
336  else
337    {
338      /* unknown strings are treated as 'horiz-vert' */
339      DBG(1, "get_barcode_search_mode: unrecognized string `%s'\n", s);
340      i = 9;
341    }
342
343  return i;
344}
345
346static void
347appendStdList(BH_Info *sc, SANE_Int res)
348{
349  /*  append entry to resolution list - a SANE_WORD_LIST */
350  sc->resStdList[sc->resStdList[0]+1] = res;
351  sc->resStdList[0]++;
352}
353
354static void
355ScannerDump(BH_Scanner *s)
356{
357  int i;
358  BH_Info *info;
359  SANE_Device *sdev;
360
361  info = &s->hw->info;
362  sdev = &s->hw->sane;
363
364  DBG (1, "SANE Device: '%s' Vendor: '%s' Model: '%s' Type: '%s'\n",
365	 sdev->name,
366	 sdev->vendor,
367	 sdev->model,
368	 sdev->type);
369
370  DBG (1, "Type: '%s' Vendor: '%s' Product: '%s' Revision: '%s'\n",
371	 print_devtype(info->devtype),
372	 info->vendor,
373	 info->product,
374	 info->revision);
375
376  DBG (1, "Automatic Document Feeder:%s\n",
377	 info->canADF ? " <Installed>" : " <Not Installed>");
378
379  DBG (1, "Colors:%s%s\n", info->colorBandW ? " <Black and White>" : "",
380	 info->colorHalftone ? " <Halftone>" : "");
381
382  DBG (1, "Data processing:%s%s%s%s%s%s\n",
383	 info->canWhiteFrame ? " <White Frame>" : "",
384	 info->canBlackFrame ? " <Black Frame>" : "",
385	 info->canEdgeExtract ? " <Edge Extraction>" : "",
386	 info->canNoiseFilter ? " <Noise Filter>" : "",
387	 info->canSmooth ? " <Smooth>" : "",
388	 info->canLineBold ? " <Line Bolding>" : "");
389
390  DBG (1, "Compression:%s%s%s\n",
391	 info->comprG3_1D ? " <Group 3, 1D>" : "",
392	 info->comprG3_2D ? " <Group 3, 2D>" : "",
393	 info->comprG4 ? " <Group 4>" : "");
394
395  DBG (1, "Optional Features:%s%s%s%s\n",
396	 info->canBorderRecog ? " <Border Recognition>" : "",
397	 info->canBarCode ? " <BarCode Decoding>" : "",
398	 info->canIcon ? " <Icon Generation>" : "",
399	 info->canSection ? " <Section Support>" : "");
400
401  DBG (1, "Max bytes per scan-line: %d (%d pixels)\n",
402	 info->lineMaxBytes,
403	 info->lineMaxBytes * 8);
404
405  DBG (1, "Basic resolution (X/Y): %d/%d\n",
406	 info->resBasicX,
407	 info->resBasicY);
408
409  DBG (1, "Maximum resolution (X/Y): %d/%d\n",
410	 info->resMaxX,
411	 info->resMaxY);
412
413  DBG (1, "Minimum resolution (X/Y): %d/%d\n",
414	 info->resMinX,
415	 info->resMinY);
416
417  DBG (1, "Standard Resolutions:\n");
418  for (i = 0; i < info->resStdList[0]; i++)
419    DBG (1, " %d\n", info->resStdList[i+1]);
420
421  DBG (1, "Window Width/Height (in basic res) %d/%d (%.2f/%.2f inches)\n",
422	 info->winWidth,
423	 info->winHeight,
424	 (info->resBasicX != 0) ? ((float) info->winWidth) / info->resBasicX : 0.0,
425	 (info->resBasicY) ? ((float) info->winHeight) / info->resBasicY : 0.0);
426
427  DBG (1, "Summary:%s%s%s\n",
428	 info->canDuplex ? "Duplex Scanner" : "Simplex Scanner",
429	 info->canACE ? " (ACE capable)" : "",
430	 info->canCheckADF ? " (ADF Paper Sensor capable)" : "");
431
432  sprintf(inquiry_data, "Vendor: %s Product: %s Rev: %s %s%s%s\n",
433	 info->vendor,
434	 info->product,
435	 info->revision,
436	 info->canDuplex ? "Duplex Scanner" : "Simplex Scanner",
437	 info->canACE ? " (ACE capable)" : "",
438	 info->canCheckADF ? " (ADF Paper Sensor capable)" : "");
439
440  DBG (5, "autoborder_default=%d\n", info->autoborder_default);
441  DBG (5, "batch_default=%d\n", info->batch_default);
442  DBG (5, "deskew_default=%d\n", info->deskew_default);
443  DBG (5, "check_adf_default=%d\n", info->check_adf_default);
444  DBG (5, "duplex_default=%d\n", info->duplex_default);
445  DBG (5, "timeout_adf_default=%d\n", info->timeout_adf_default);
446  DBG (5, "timeout_manual_default=%d\n", info->timeout_manual_default);
447  DBG (5, "control_panel_default=%d\n", info->control_panel_default);
448
449}
450
451static SANE_Status
452test_unit_ready (int fd)
453{
454  static SANE_Byte cmd[6];
455  SANE_Status status;
456  DBG (3, "test_unit_ready called\n");
457
458  cmd[0] = BH_SCSI_TEST_UNIT_READY;
459  memset (cmd, 0, sizeof (cmd));
460  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0);
461
462  return status;
463}
464
465static SANE_Status
466object_position (BH_Scanner *s)
467{
468  static SANE_Byte cmd[10];
469  SANE_Status status;
470  DBG (3, "object_position called\n");
471
472  memset (cmd, 0, sizeof (cmd));
473  cmd[0] = BH_SCSI_OBJECT_POSITION;
474  cmd[1] = 0x01;
475  status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0);
476
477  return status;
478}
479
480static SANE_Status
481read_barcode_data (BH_Scanner *s, FILE *fp)
482{
483  static SANE_Byte cmd[10];
484  SANE_Status status;
485  SANE_Int num_found = 0;
486  double w, l, x, y, res;
487  struct barcode_data buf;
488  size_t buf_size = sizeof(buf);
489  DBG (3, "read_barcode_data called\n");
490
491  memset (&cmd, 0, sizeof (cmd));
492  cmd[0] = BH_SCSI_READ_SCANNED_DATA;
493  cmd[2] = s->readlist[s->readptr];
494  _lto3b(buf_size, &cmd[6]); /* transfer length */
495
496  s->barcode_not_found = SANE_FALSE;
497  do {
498    memset (&buf, 0, sizeof(buf));
499    status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size);
500    if (status != SANE_STATUS_GOOD)
501      break;
502    if (s->barcode_not_found == SANE_TRUE)
503      break;
504
505    num_found++;
506
507    buf.barcodedata[sizeof(buf.barcodedata)-1] = '\0';
508
509    /* calculate the bounding rectangle */
510    x = MIN((int) _2btol(buf.posxb), (int) _2btol(buf.posxa));
511    y = MIN((int) _2btol(buf.posyb), (int) _2btol(buf.posyd));
512    w = MAX((int) _2btol(buf.posxd), (int) _2btol(buf.posxd)) - x;
513    l = MAX((int) _2btol(buf.posya), (int) _2btol(buf.posyc)) - y;
514    /* convert from pixels to mm */
515    res = _OPT_VAL_WORD(s, OPT_RESOLUTION);
516    if (res <= 0.0)
517      {
518	/* avoid divide by zero */
519	DBG(1, "read_barcode_data: warning: "
520	    "encountered bad resolution value '%f', replacing with '%f'\n",
521	    res, 200.0);
522	res = 200.0;
523      }
524    x = x * MM_PER_INCH / res;
525    y = y * MM_PER_INCH / res;
526    w = w * MM_PER_INCH / res;
527    l = l * MM_PER_INCH / res;
528    /* add a bit of a border around the edges */
529    x = MAX(0.0, x - BH_DECODE_FUDGE);
530    y = MAX(0.0, y - BH_DECODE_FUDGE);
531    w += (BH_DECODE_FUDGE * 4);
532    l += (BH_DECODE_FUDGE * 4);
533
534    /* write the decoded barcode data into the file */
535    fprintf(fp, "<barcode>\n <section>%s</section>\n",
536	    print_read_type((int) s->readlist[s->readptr]));
537    fprintf(fp, " <type>%s</type>\n <status-flag>%d</status-flag>\n",
538	    print_barcodetype((int) _2btol(buf.barcodetype)),
539	    (int) _2btol(buf.statusflag));
540    fprintf(fp, " <orientation>%s</orientation>\n",
541	    print_orientation((int) _2btol(buf.barcodeorientation)));
542    fprintf(fp, " <location>\n  <tl><x>%d</x><y>%d</y></tl>\n",
543	    (int) _2btol(buf.posxb), (int) _2btol(buf.posyb));
544    fprintf(fp, "  <tr><x>%d</x><y>%d</y></tr>\n",
545	    (int) _2btol(buf.posxd), (int) _2btol(buf.posyd));
546    fprintf(fp, "  <bl><x>%d</x><y>%d</y></bl>\n",
547	    (int) _2btol(buf.posxa), (int) _2btol(buf.posya));
548    fprintf(fp, "  <br><x>%d</x><y>%d</y></br>\n </location>\n",
549	    (int) _2btol(buf.posxc), (int) _2btol(buf.posyc));
550    fprintf(fp, " <rectangle>%.2fx%.2f+%.2f+%.2f</rectangle>\n",
551	    w, l, x, y);
552    fprintf(fp, " <search-time>%d</search-time>\n <length>%d</length>\n",
553	    (int) _2btol(buf.barcodesearchtime),
554	    (int) buf.barcodelen);
555    fprintf(fp, " <data>%s</data>\n</barcode>\n",
556	    buf.barcodedata);
557  } while (num_found <= BH_DECODE_TRIES);
558
559  DBG (3, "read_barcode_data: found %d barcodes, returning %s\n",
560       num_found, sane_strstatus(status));
561
562  return status;
563}
564
565static SANE_Status
566read_icon_data (BH_Scanner *s)
567{
568  static SANE_Byte cmd[10];
569  SANE_Status status;
570  struct icon_data buf;
571  size_t buf_size = sizeof(buf);
572  DBG (3, "read_icon_data called\n");
573
574  memset (&cmd, 0, sizeof (cmd));
575  cmd[0] = BH_SCSI_READ_SCANNED_DATA;
576  cmd[2] = s->readlist[s->readptr];
577  _lto3b(buf_size, &cmd[6]); /* transfer length */
578
579  memset (&buf, 0, sizeof(buf));
580
581  status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size);
582
583  /* set the fields in the scanner handle for later reference */
584  s->iconwidth = _4btol(buf.iconwidth);
585  s->iconlength = _4btol(buf.iconlength);
586
587  DBG(3, "read_icon_data: windowwidth:%lu, windowlength:%lu\n",
588      _4btol(buf.windowwidth),
589      _4btol(buf.windowlength));
590  DBG(3, "read_icon_data: iconwidth:%lu, iconlength:%lu, iconwidth(bytes):%lu\n",
591      _4btol(buf.iconwidth),
592      _4btol(buf.iconlength),
593      _4btol(buf.iconwidthbytes));
594  DBG(3, "read_icon_data: bitordering:%02x, icondatalen:%lu\n",
595      buf.bitordering,
596      _4btol(buf.icondatalen));
597
598  DBG (3, "read_icon_data returning %d\n", status);
599
600  return status;
601}
602
603static SANE_Status
604read_barfile (BH_Scanner *s, void *buf, size_t *buf_size)
605{
606  SANE_Status status = SANE_STATUS_GOOD;
607  size_t nread;
608  DBG (3, "read_barfile called (%lu bytes)\n", (u_long) *buf_size);
609
610  if (s->barf != NULL)
611    {
612      /* this function needs to set InvalidBytes so it looks
613       * like a B&H scsi EOF
614       */
615      if ((nread = fread(buf, 1, *buf_size, s->barf)) < *buf_size)
616	{
617	  /* set InvalidBytes */
618	  s->InvalidBytes = *buf_size - nread;
619
620	  if (ferror(s->barf))
621	    {
622	      status = SANE_STATUS_IO_ERROR;
623	      fclose(s->barf);
624	      s->barf = NULL;
625	      unlink(s->barfname);
626	    }
627	  else if (feof(s->barf))
628	    {
629	      /* it also needs to close the file and delete it when EOF is
630	       * reached.
631	       */
632	      fclose(s->barf);
633	      s->barf = NULL;
634	      unlink(s->barfname);
635	    }
636	}
637    }
638  else
639    {
640      /* set InvalidBytes */
641      s->InvalidBytes = *buf_size;
642    }
643
644  return status;
645}
646
647static SANE_Status
648read_data (BH_Scanner *s, void *buf, size_t *buf_size)
649{
650  static SANE_Byte cmd[10];
651  SANE_Status status;
652  DBG (3, "read_data called (%lu bytes)\n", (u_long) *buf_size);
653
654  if (s->readlist[s->readptr] == BH_SCSI_READ_TYPE_SENDBARFILE)
655    {
656      /* call special barcode data read function. */
657      status = read_barfile(s, buf, buf_size);
658    }
659  else
660    {
661      memset (&cmd, 0, sizeof (cmd));
662      cmd[0] = BH_SCSI_READ_SCANNED_DATA;
663      cmd[2] = s->readlist[s->readptr];
664      _lto3b(*buf_size, &cmd[6]); /* transfer length */
665
666      status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, buf_size);
667    }
668
669  return status;
670}
671
672static SANE_Status
673mode_select_measurement (BH_Scanner *s)
674{
675  static struct {
676    SANE_Byte cmd[6];
677    struct mode_page_03 mp;
678  } select_cmd;
679  SANE_Status status;
680
681  DBG (3, "mode_select_measurement called (bmu:%d mud:%d)\n",
682       s->bmu, s->mud);
683
684  memset (&select_cmd, 0, sizeof (select_cmd));
685  select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
686  select_cmd.cmd[1] = 0x10;
687  select_cmd.cmd[4] = sizeof(select_cmd.mp);
688
689  select_cmd.mp.pagecode = BH_MODE_MEASUREMENT_PAGE_CODE;
690  select_cmd.mp.paramlen = 0x06;
691  select_cmd.mp.bmu = s->bmu;
692  _lto2b(s->mud, select_cmd.mp.mud);
693
694  status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
695
696  return status;
697}
698
699static SANE_Status
700mode_select_timeout (BH_Scanner *s)
701{
702  static struct {
703    SANE_Byte cmd[6];
704    struct mode_page_20 mp;
705  } select_cmd;
706  SANE_Status status;
707
708  DBG (3, "mode_select_timeout called\n");
709
710  memset (&select_cmd, 0, sizeof (select_cmd));
711  select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
712  select_cmd.cmd[1] = 0x10;
713  select_cmd.cmd[4] = sizeof(select_cmd.mp);
714
715  select_cmd.mp.pagecode = BH_MODE_TIMEOUT_PAGE_CODE;
716  select_cmd.mp.paramlen = 0x06;
717  select_cmd.mp.timeoutmanual = _OPT_VAL_WORD(s, OPT_TIMEOUT_MANUAL);
718  select_cmd.mp.timeoutadf = _OPT_VAL_WORD(s, OPT_TIMEOUT_ADF);
719
720  status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
721
722  return status;
723}
724
725static SANE_Status
726mode_select_icon (BH_Scanner *s)
727{
728  static struct {
729    SANE_Byte cmd[6];
730    struct mode_page_21 mp;
731  } select_cmd;
732  SANE_Status status;
733
734  DBG (3, "mode_select_icon called\n");
735
736  memset (&select_cmd, 0, sizeof (select_cmd));
737  select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
738  select_cmd.cmd[1] = 0x10;
739  select_cmd.cmd[4] = sizeof(select_cmd.mp);
740
741  select_cmd.mp.pagecode = BH_MODE_ICON_PAGE_CODE;
742  select_cmd.mp.paramlen = 0x06;
743  _lto2b(_OPT_VAL_WORD(s, OPT_ICON_WIDTH), select_cmd.mp.iconwidth);
744  _lto2b(_OPT_VAL_WORD(s, OPT_ICON_LENGTH), select_cmd.mp.iconlength);
745
746  status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
747
748  return status;
749}
750
751static SANE_Status
752mode_select_barcode_priority (BH_Scanner *s)
753{
754  static struct {
755    SANE_Byte cmd[6];
756    struct mode_page_30 mp;
757  } select_cmd;
758  SANE_Status status;
759  int i;
760
761  DBG (3, "mode_select_barcode_priority called\n");
762
763  memset (&select_cmd, 0, sizeof (select_cmd));
764  select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
765  select_cmd.cmd[1] = 0x10;
766  select_cmd.cmd[4] = sizeof(select_cmd.mp);
767
768  select_cmd.mp.pagecode = BH_MODE_BARCODE_PRIORITY_PAGE_CODE;
769  select_cmd.mp.paramlen = 0x06;
770
771  for (i = 0; i < NUM_SEARCH_BARS; i++)
772    {
773      /* anything after a 'none' is ignored */
774      if ((select_cmd.mp.priority[i] = s->search_bars[i]) == 0) break;
775    }
776
777  status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
778
779  return status;
780}
781
782static SANE_Status
783mode_select_barcode_param1 (BH_Scanner *s)
784{
785  static struct {
786    SANE_Byte cmd[6];
787    struct mode_page_31 mp;
788  } select_cmd;
789  SANE_Status status;
790
791  DBG (3, "mode_select_barcode_param1 called\n");
792
793  memset (&select_cmd, 0, sizeof (select_cmd));
794  select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
795  select_cmd.cmd[1] = 0x10;
796  select_cmd.cmd[4] = sizeof(select_cmd.mp);
797
798  select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM1_PAGE_CODE;
799  select_cmd.mp.paramlen = 0x06;
800
801  _lto2b((SANE_Int)_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BARCODE_HMIN), select_cmd.mp.minbarheight);
802  select_cmd.mp.searchcount = _OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_COUNT);
803  select_cmd.mp.searchmode =
804    get_barcode_search_mode(_OPT_VAL_STRING(s, OPT_BARCODE_SEARCH_MODE));
805  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_TIMEOUT), select_cmd.mp.searchtimeout);
806
807  status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
808
809  return status;
810}
811
812static SANE_Status
813mode_select_barcode_param2 (BH_Scanner *s)
814{
815  static struct {
816    SANE_Byte cmd[6];
817    struct mode_page_32 mp;
818  } select_cmd;
819  SANE_Status status;
820  size_t len;
821
822  DBG (3, "mode_select_barcode_param2 called\n");
823
824  /* first we'll do a mode sense, then we'll overwrite with
825   * our new values, and then do a mode select
826   */
827  memset (&select_cmd, 0, sizeof (select_cmd));
828  select_cmd.cmd[0] = BH_SCSI_MODE_SENSE;
829  select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM2_PAGE_CODE;
830  select_cmd.cmd[4] = sizeof(select_cmd.mp);
831
832  len = sizeof(select_cmd.mp);
833  status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd),
834			   &select_cmd.mp, &len);
835
836  if (status == SANE_STATUS_GOOD)
837    {
838      DBG(8, "mode_select_barcode_param2: sensed values: relmax:%d barmin:%d barmax:%d\n",
839	  (int) _2btol(select_cmd.mp.relmax),
840	  (int) _2btol(select_cmd.mp.barmin),
841	  (int) _2btol(select_cmd.mp.barmax));
842
843      memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd));
844      select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
845      select_cmd.cmd[1] = 0x10;
846      select_cmd.cmd[4] = sizeof(select_cmd.mp);
847
848      select_cmd.mp.modedatalen = 0x00;
849      select_cmd.mp.mediumtype = 0x00;
850      select_cmd.mp.devicespecificparam = 0x00;
851      select_cmd.mp.blockdescriptorlen = 0x00;
852
853      select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM2_PAGE_CODE;
854      select_cmd.mp.paramlen = 0x06;
855
856      /* only overwrite the default values if the option is non-zero */
857      if (_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX) != 0)
858	{
859	  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), select_cmd.mp.relmax);
860	}
861      if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN) != 0)
862	{
863	  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), select_cmd.mp.barmin);
864	}
865      if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX) != 0)
866	{
867	  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX), select_cmd.mp.barmax);
868	}
869
870      DBG(8, "mode_select_barcode_param2: param values: relmax:%d barmin:%d barmax:%d\n",
871	  (int) _OPT_VAL_WORD(s, OPT_BARCODE_RELMAX),
872	  (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMIN),
873	  (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMAX));
874
875      DBG(8, "mode_select_barcode_param2: select values: relmax:%d barmin:%d barmax:%d\n",
876	  (int) _2btol(select_cmd.mp.relmax),
877	  (int) _2btol(select_cmd.mp.barmin),
878	  (int) _2btol(select_cmd.mp.barmax));
879
880      status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
881    }
882
883  return status;
884}
885
886static SANE_Status
887mode_select_barcode_param3 (BH_Scanner *s)
888{
889  static struct {
890    SANE_Byte cmd[6];
891    struct mode_page_33 mp;
892  } select_cmd;
893  SANE_Status status;
894  size_t len;
895
896  DBG (3, "mode_select_barcode_param3 called\n");
897
898  /* first we'll do a mode sense, then we'll overwrite with
899   * our new values, and then do a mode select
900   */
901  memset (&select_cmd, 0, sizeof (select_cmd));
902  select_cmd.cmd[0] = BH_SCSI_MODE_SENSE;
903  select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM3_PAGE_CODE;
904  select_cmd.cmd[4] = sizeof(select_cmd.mp);
905
906  len = sizeof(select_cmd.mp);
907  status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd),
908			   &select_cmd.mp, &len);
909
910  if (status == SANE_STATUS_GOOD)
911    {
912      DBG(8, "mode_select_barcode_param3: sensed values: contrast:%d patchmode:%d\n",
913	  (int) _2btol(select_cmd.mp.barcodecontrast),
914	  (int) _2btol(select_cmd.mp.patchmode));
915
916      memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd));
917      select_cmd.cmd[0] = BH_SCSI_MODE_SELECT;
918      select_cmd.cmd[1] = 0x10;
919      select_cmd.cmd[4] = sizeof(select_cmd.mp);
920
921      select_cmd.mp.modedatalen = 0x00;
922      select_cmd.mp.mediumtype = 0x00;
923      select_cmd.mp.devicespecificparam = 0x00;
924      select_cmd.mp.blockdescriptorlen = 0x00;
925
926      select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM3_PAGE_CODE;
927      select_cmd.mp.paramlen = 0x06;
928
929      /* only overwrite the default values if the option is non-zero */
930      if (_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST) != 0)
931	{
932	  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), select_cmd.mp.barcodecontrast);
933	}
934      if (_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE) != 0)
935	{
936	  _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE), select_cmd.mp.patchmode);
937	}
938
939      DBG(8, "mode_select_barcode_param3: param values: contrast:%d patchmode:%d\n",
940	  (int) _OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST),
941	  (int) _OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE));
942
943      DBG(8, "mode_select_barcode_param3: select values: contrast:%d patchmode:%d\n",
944	  (int) _2btol(select_cmd.mp.barcodecontrast),
945	  (int) _2btol(select_cmd.mp.patchmode));
946
947      status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0);
948    }
949
950  return status;
951}
952
953static SANE_Status
954inquiry (int fd, void *buf, size_t *buf_size, SANE_Byte evpd, SANE_Byte page_code)
955{
956  static SANE_Byte cmd[6];
957  SANE_Status status;
958  DBG (3, "inquiry called\n");
959
960  memset (cmd, 0, sizeof (cmd));
961  cmd[0] = BH_SCSI_INQUIRY;
962  cmd[1] = evpd;
963  cmd[2] = page_code;
964  cmd[4] = *buf_size;
965
966  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size);
967
968  return status;
969}
970
971static SANE_Status
972set_window (BH_Scanner *s, SANE_Byte batchmode)
973{
974  static struct {
975    SANE_Byte cmd[10];
976    SANE_Byte hdr[8];
977    struct window_data window;
978  } set_window_cmd;
979  SANE_Status status;
980  SANE_Int width, length, i, format, rotation, deskew ;
981
982  DBG (3, "set_window called\n");
983
984  /* set to thousandths for set_window */
985  s->bmu = BH_UNIT_INCH;
986  s->mud = 1000;
987  status = mode_select_measurement(s);
988  if (status != SANE_STATUS_GOOD)
989    return status;
990
991  memset (&set_window_cmd, 0, sizeof (set_window_cmd));
992  set_window_cmd.cmd[0] = BH_SCSI_SET_WINDOW;
993  DBG(3, "set_window: sizeof(hdr) %d, sizeof(window): %d\n",
994      (int)sizeof(set_window_cmd.hdr), (int)sizeof(set_window_cmd.window));
995
996  _lto3b(sizeof(set_window_cmd.hdr) + sizeof(set_window_cmd.window),
997	 &set_window_cmd.cmd[6]);
998
999  _lto2b(256, &set_window_cmd.hdr[6]);
1000
1001  set_window_cmd.window.windowid = 0;
1002  set_window_cmd.window.autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER);
1003  DBG (5, "autoborder set to=%d\n", set_window_cmd.window.autoborder);
1004  _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.xres);
1005  _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.yres);
1006  _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X), set_window_cmd.window.ulx);
1007  _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y), set_window_cmd.window.uly);
1008
1009  width = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X) -
1010	 _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X));
1011  length = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y) -
1012	 _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y));
1013
1014  _lto4b(width, set_window_cmd.window.windowwidth);
1015  _lto4b(length, set_window_cmd.window.windowlength);
1016
1017  /* brightness (1-255) 0 is default, aka 128.  Ignored with ACE scanners */
1018  set_window_cmd.window.brightness = _OPT_VAL_WORD(s, OPT_BRIGHTNESS);
1019  /* threshold (1-255) 0 is default, aka 128.  Ignored with ACE scanners */
1020  set_window_cmd.window.threshold = _OPT_VAL_WORD(s, OPT_THRESHOLD);
1021  /*!!! contrast (not used) */
1022  /*!!! set_window_cmd.window.contrast = _OPT_VAL_WORD(s, OPT_CONTRAST); */
1023  /* imagecomposition 0x00 lineart, 0x01 dithered/halftone, 0x02 grayscale*/
1024  set_window_cmd.window.imagecomposition =
1025    get_scan_mode_id(_OPT_VAL_STRING(s, OPT_SCAN_MODE));
1026
1027  set_window_cmd.window.bitsperpixel = 0x01;
1028  /*!!! halftone code (not used) */
1029  /*!!! halftone id (not used) */
1030
1031  set_window_cmd.window.paddingtype = 0x03; /* truncate byte */
1032  if (_OPT_VAL_WORD(s, OPT_NEGATIVE) == SANE_TRUE) {
1033    /* reverse image format (valid when bitsperpixel=1)
1034     * 0x00 normal, 0x01 reversed.  This is bit 7 of paddingtype.
1035     */
1036    set_window_cmd.window.paddingtype |= 0x80;
1037  }
1038
1039  set_window_cmd.window.bitordering[0] = 0x00;
1040
1041  /* we must always sent plain gray data in preview mode */
1042  format = (_OPT_VAL_WORD(s, OPT_PREVIEW)) ?
1043    BH_COMP_NONE :
1044    get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION));
1045
1046  switch (format)
1047    {
1048    case BH_COMP_G31D:
1049      set_window_cmd.window.compressiontype = 0x01;
1050      set_window_cmd.window.compressionarg = 0x00;
1051      set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */
1052      break;
1053    case BH_COMP_G32D:
1054      set_window_cmd.window.compressiontype = 0x02;
1055      set_window_cmd.window.compressionarg = 0x04;
1056      set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */
1057      break;
1058    case BH_COMP_G42D:
1059      set_window_cmd.window.compressiontype = 0x03;
1060      set_window_cmd.window.compressionarg = 0x00;
1061      set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */
1062      break;
1063    case BH_COMP_NONE:
1064    default:
1065      set_window_cmd.window.compressiontype = 0x00;
1066      set_window_cmd.window.compressionarg = 0x00;
1067      set_window_cmd.window.bitordering[1] = 0x00; /* n/a */
1068      break;
1069    }
1070
1071  /* rotation and deskew settings, if autoborder is turned on */
1072  if(set_window_cmd.window.autoborder){ /*--- setting byte 46 of the window descriptor block only works with autoborder */
1073    rotation = get_rotation_id(_OPT_VAL_STRING(s, OPT_ROTATION));
1074    if (_OPT_VAL_WORD(s, OPT_DESKEW) == SANE_TRUE) deskew = BH_DESKEW_ENABLE;
1075    else deskew = BH_DESKEW_DISABLE;
1076    set_window_cmd.window.border_rotation = ( rotation | deskew );  /*--- deskew assumes autoborder */
1077  }
1078
1079  /* remote - 0x00 ACE set in window; 0x01 ACE set by control panel */
1080  set_window_cmd.window.remote = _OPT_VAL_WORD(s, OPT_CONTROL_PANEL);
1081  if (set_window_cmd.window.remote == 0x00) {
1082    /* acefunction (ignored on non-ACE scanners) */
1083    set_window_cmd.window.acefunction = _OPT_VAL_WORD(s, OPT_ACE_FUNCTION);
1084    /* acesensitivity (ignored on non-ACE scanners) */
1085    set_window_cmd.window.acesensitivity = _OPT_VAL_WORD(s, OPT_ACE_SENSITIVITY);
1086  }
1087
1088  set_window_cmd.window.batchmode = batchmode;
1089
1090  /* fill in the section descriptor blocks */
1091  for (i = 0; i < s->num_sections; i++)
1092    {
1093      BH_SectionBlock *b;
1094
1095      b = &set_window_cmd.window.sectionblock[i];
1096
1097      _lto4b(s->sections[i].left, b->ul_x);
1098      _lto4b(s->sections[i].top, b->ul_y);
1099      _lto4b(s->sections[i].width, b->width);
1100      _lto4b(s->sections[i].length, b->length);
1101      b->compressiontype = s->sections[i].compressiontype;
1102      b->compressionarg = s->sections[i].compressionarg;
1103    }
1104
1105  status = sanei_scsi_cmd (s->fd, &set_window_cmd, sizeof (set_window_cmd), 0, 0);
1106  DBG (5, "sanei_scsi_cmd executed, status=%d\n", status );
1107  if (status != SANE_STATUS_GOOD)
1108    return status;
1109
1110  /* set to points for reading */
1111  s->bmu = BH_UNIT_POINT;
1112  s->mud = 1;
1113  status = mode_select_measurement(s);
1114
1115  return status;
1116}
1117
1118static SANE_Status
1119get_window (BH_Scanner *s, SANE_Int *w, SANE_Int *h, SANE_Bool backpage)
1120{
1121  SANE_Byte cmd[10];
1122  static struct {
1123    SANE_Byte hdr[8];
1124    struct window_data window;
1125  } get_window_data;
1126  SANE_Status status;
1127  SANE_Int x, y, i = 0, get_window_delay = 1;
1128  SANE_Bool autoborder;
1129  size_t len;
1130
1131  DBG (3, "get_window called\n");
1132
1133  autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER) == 1;
1134
1135  while (1)
1136    {
1137      i++;
1138      memset (&cmd, 0, sizeof (cmd));
1139      memset (&get_window_data, 0, sizeof (get_window_data));
1140
1141      cmd[0] = BH_SCSI_GET_WINDOW;
1142      _lto3b(sizeof(get_window_data), &cmd[6]);
1143
1144      _lto2b(256, &get_window_data.hdr[6]);
1145
1146      get_window_data.window.windowid = (backpage == SANE_TRUE) ? 1 : 0;
1147
1148      len = sizeof(get_window_data);
1149      status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd),
1150			       &get_window_data, &len);
1151      if (status == SANE_STATUS_GOOD)
1152	{
1153	  x =_4btol(get_window_data.window.ulx);
1154	  y =_4btol(get_window_data.window.uly);
1155	  *w =_4btol(get_window_data.window.windowwidth);
1156	  *h =_4btol(get_window_data.window.windowlength);
1157
1158	  if (autoborder)
1159	    {
1160	      /* we try repeatedly until we get the autoborder bit set */
1161	      if (get_window_data.window.autoborder != 1 &&
1162		  i < BH_AUTOBORDER_TRIES)
1163		{
1164	          DBG (5, "waiting %d second[s], try: %d\n",get_window_delay,i);
1165		  sleep(get_window_delay);  /*--- page 4-5 of B&H Copiscan 8000 ESC OEM Tech Manual */
1166                                            /*--- requires at least 50ms wait between each GET WINDOW command */
1167                                            /*--- experience shows that this can take 3 to 4 seconds */
1168		  continue;
1169		}
1170	      if (get_window_data.window.autoborder != 1)
1171		{
1172		  DBG(1, "Automatic Border Detection not done within %d tries\n",
1173		      BH_AUTOBORDER_TRIES);
1174		  status = SANE_STATUS_IO_ERROR;
1175		}
1176             DBG (0, "page dimension: wide:%d high:%d \n",*w,*h);
1177	    }
1178	  DBG (3, "*** Window size: %dx%d+%d+%d\n", *w, *h, x, y);
1179	  DBG (5, "*** get_window found autoborder=%02xh\n", get_window_data.window.autoborder);
1180	  DBG (5, "*** get_window found border_rotation=%02xh\n", get_window_data.window.border_rotation);
1181	}
1182
1183      /* we are 'outta here' */
1184      break;
1185    }
1186
1187  return status;
1188}
1189
1190static SANE_Status
1191get_parameters (SANE_Handle handle, SANE_Parameters *params)
1192{
1193  BH_Scanner *s = handle;
1194  SANE_Int width, length, res, comp;
1195  double br_x, tl_x, br_y, tl_y;
1196  SANE_Frame format;
1197
1198  DBG(3, "get_parameters called\n");
1199
1200  memset (&s->params, 0, sizeof (s->params));
1201
1202  res = _OPT_VAL_WORD(s, OPT_RESOLUTION);
1203
1204  /* make best-effort guess at what parameters will look like once
1205     the scan starts.  */
1206
1207  br_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X);
1208  br_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y);
1209  tl_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X);
1210  tl_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y);
1211
1212  width = (br_x - tl_x + 1) * res / 1000.0;
1213  length = (br_y - tl_y + 1) * res / 1000.0;
1214
1215  /* figure out the default image format for front/back pages */
1216  comp = get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION));
1217  switch (comp)
1218    {
1219    case BH_COMP_G31D:
1220      format = SANE_FRAME_G31D;
1221      break;
1222    case BH_COMP_G32D:
1223      format = SANE_FRAME_G32D;
1224      break;
1225    case BH_COMP_G42D:
1226      format = SANE_FRAME_G42D;
1227      break;
1228    case BH_COMP_NONE:
1229    default:
1230      format = SANE_FRAME_GRAY;
1231      break;
1232    }
1233
1234  if (s->scanning)
1235    {
1236      SANE_Int w, l, status;
1237      SANE_Byte itemtype;
1238
1239      itemtype = s->readlist[s->readptr];
1240      /* update parameters based on the current item */
1241
1242      status = SANE_STATUS_GOOD;
1243      if (itemtype == BH_SCSI_READ_TYPE_FRONT)
1244	{
1245	  DBG (3, "get_parameters: sending GET WINDOW (front)\n");
1246	  status = get_window (s, &w, &l, SANE_FALSE);
1247	  if (status == SANE_STATUS_GOOD)
1248	    {
1249	      width = w;
1250	      length = l;
1251	    }
1252	}
1253      else if (itemtype == BH_SCSI_READ_TYPE_BACK)
1254	{
1255	  DBG (3, "get_parameters: sending GET WINDOW (back)\n");
1256	  status = get_window (s, &w, &l, SANE_TRUE);
1257	  if (status == SANE_STATUS_GOOD)
1258	    {
1259	      width = w;
1260	      length = l;
1261	    }
1262	}
1263      else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON ||
1264	       itemtype == BH_SCSI_READ_TYPE_BACK_ICON)
1265	{
1266	  /* the icon is never compressed */
1267	  format = SANE_FRAME_GRAY;
1268	  width = s->iconwidth;
1269	  length = s->iconlength;
1270	}
1271      else if (itemtype > BH_SCSI_READ_TYPE_FRONT &&
1272	       itemtype <= (BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS))
1273	{
1274	  /* a front section */
1275	  SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_FRONT;
1276
1277	  format = s->sections[sectnum - 1].format;
1278	  /* convert from thousandths to pixels */
1279	  width = s->sections[sectnum - 1].width * res / 1000.0;
1280	  length = s->sections[sectnum - 1].length * res / 1000.0;
1281	}
1282      else if (itemtype > BH_SCSI_READ_TYPE_BACK &&
1283	       itemtype <= (BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS))
1284	{
1285	  /* a back section */
1286	  SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_BACK;
1287
1288	  format = s->sections[sectnum - 1].format;
1289	  /* convert from thousandths to pixels */
1290	  width = s->sections[sectnum - 1].width * res / 1000.0;
1291	  length = s->sections[sectnum - 1].length * res / 1000.0;
1292	}
1293      else if ( (itemtype >= BH_SCSI_READ_TYPE_BACK_BARCODE &&
1294		 itemtype <= (BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS)) ||
1295		(itemtype >= BH_SCSI_READ_TYPE_FRONT_BARCODE &&
1296		 itemtype <= (BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS)) )
1297	{
1298	  /* decoded barcode data */
1299	  format = SANE_FRAME_TEXT;
1300	  width = 8;
1301	  length = -1;
1302	}
1303      else if (itemtype == BH_SCSI_READ_TYPE_SENDBARFILE)
1304	{
1305	  /* decoded barcode data file */
1306	  format = SANE_FRAME_TEXT;
1307	  width = 8;
1308	  length = -1;
1309	}
1310      else
1311	{
1312	  format = SANE_FRAME_GRAY;
1313	  width = 8;
1314	  length = -1;
1315	  DBG(1, "get_parameters: unrecognized read itemtype: %d\n",
1316	      itemtype);
1317	}
1318
1319      if (status != SANE_STATUS_GOOD)
1320	{
1321	  DBG(1, "get_parameters: failed\n");
1322	  return status;
1323	}
1324    }
1325
1326  if (res <= 0 || width <= 0)
1327    {
1328      DBG(1, "get_parameters:illegal parameters res=%d, width=%d, length=%d\n",
1329	  res, width, length);
1330      return SANE_STATUS_INVAL;
1331    }
1332
1333  /* we disable our compression/barcode formats in preview as well
1334   * as with the disable_optional_frames configuration option.  NOTE:
1335   * we may still be delivering 'wierd' data and lying about it being _GRAY!
1336   */
1337  if (format != SANE_FRAME_GRAY &&
1338      (_OPT_VAL_WORD(s, OPT_PREVIEW) || disable_optional_frames))
1339    {
1340      DBG(1, "get_parameters: warning: delivering %s data as gray",
1341	  sane_strframe(format));
1342      format = SANE_FRAME_GRAY;
1343    }
1344
1345  s->params.format = format;
1346  s->params.depth = 1;
1347  s->params.last_frame = SANE_TRUE;
1348  s->params.pixels_per_line = width;
1349  s->params.lines = length;
1350  s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8;
1351  /* The Bell and Howell truncates to the byte */
1352  s->params.pixels_per_line = s->params.bytes_per_line * 8;
1353
1354  if (params)
1355    *params = s->params;
1356
1357  DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, "
1358       "lines=%d, dpi=%d\n",
1359       (int) s->params.format,
1360       s->params.pixels_per_line,
1361       s->params.bytes_per_line,
1362       s->params.lines,
1363       res);
1364
1365  return SANE_STATUS_GOOD;
1366}
1367
1368static SANE_Status
1369section_parse(const char *val, BH_Section *sect, SANE_Int res, SANE_Int comp)
1370{
1371  SANE_Status status = SANE_STATUS_INVAL;
1372  char buf[255+1], *x, *y, *w, *l, *f, *ep;
1373  const char *seps = "x+:";
1374  double mm, fpixels;
1375  u_long pixels;
1376
1377  DBG(3, "section_parse called\n");
1378
1379  /* a section option looks something like this:
1380   * <width>x<length>+<tl-x>+<tl-y>:<functioncodes>
1381   * Example:
1382   * 76.2x25.4+50.8+0:frontbar:back:front
1383   * the width, length, tl-x, and tl-y are in mm.
1384   * the function codes are one or more of:
1385   * front, back, frontbar, backbar, frontpatch, backpatch
1386   */
1387  if (strlen(val) > sizeof(buf) - 1)
1388    {
1389      DBG(1, "section_parse: option string too long\n");
1390      status = SANE_STATUS_INVAL;
1391    }
1392  else
1393    {
1394      do {
1395	strcpy(buf, val);
1396
1397	x = y = w = l = f = NULL;
1398	w = strtok(buf, seps);
1399	if (w) l = strtok(NULL, seps);
1400	if (l) x = strtok(NULL, seps);
1401	if (x) y = strtok(NULL, seps);
1402	if (y) f = strtok(NULL, seps);
1403	if (!x || !y || !w || !l) break;
1404
1405	mm = strtod(x, &ep);
1406	if (*ep != '\0' || errno == ERANGE || mm < 0.0) break;
1407	sect->left = mm * 1000.0 / MM_PER_INCH;
1408
1409	mm = strtod(y, &ep);
1410	if (*ep != '\0' || errno == ERANGE || mm < 0.0) break;
1411	sect->top = mm * 1000.0 / MM_PER_INCH;
1412
1413	mm = strtod(w, &ep);
1414	if (*ep != '\0' || errno == ERANGE || mm < 0.0) break;
1415	sect->width = mm * 1000.0 / MM_PER_INCH;
1416	/* the window width must be truncated to 16 bit points */
1417	fpixels = sect->width * res / 1000.0;
1418	pixels = fpixels / 16;
1419	sect->width = pixels * 16 * 1000 / res;
1420
1421	mm = strtod(l, &ep);
1422	if (*ep != '\0' || errno == ERANGE || mm < 0.0) break;
1423	sect->length = mm * 1000.0 / MM_PER_INCH;
1424
1425	status = SANE_STATUS_GOOD;
1426	while (f)
1427	  {
1428	    /* parse the function modifiers and set flags */
1429	    if (strcmp(f, "front") == 0)
1430	      sect->flags |= BH_SECTION_FRONT_IMAGE;
1431	    else if (strcmp(f, "frontbar") == 0)
1432	      sect->flags |= BH_SECTION_FRONT_BAR;
1433	    else if (strcmp(f, "frontpatch") == 0)
1434	      sect->flags |= BH_SECTION_FRONT_PATCH;
1435	    else if (strcmp(f, "back") == 0)
1436		sect->flags |= BH_SECTION_BACK_IMAGE;
1437	    else if (strcmp(f, "backbar") == 0)
1438		sect->flags |= BH_SECTION_BACK_BAR;
1439	    else if (strcmp(f, "backpatch") == 0)
1440		sect->flags |= BH_SECTION_BACK_PATCH;
1441	    else if (strcmp(f, "g42d") == 0)
1442		comp = BH_COMP_G42D;
1443	    else if (strcmp(f, "g32d") == 0)
1444		comp = BH_COMP_G32D;
1445	    else if (strcmp(f, "g31d") == 0)
1446		comp = BH_COMP_G31D;
1447	    else if (strcmp(f, "none") == 0)
1448		comp = BH_COMP_NONE;
1449	    else
1450	      DBG(1, "section_parse: ignoring unrecognized function "
1451		  "code '%s'\n", f);
1452
1453	    f = strtok(NULL, seps);
1454	  }
1455
1456	switch (comp)
1457	  {
1458	  case BH_COMP_G31D:
1459	    sect->compressiontype = 0x01;
1460	    sect->compressionarg = 0x00;
1461	    sect->format = SANE_FRAME_G31D;
1462	    break;
1463	  case BH_COMP_G32D:
1464	    sect->compressiontype = 0x02;
1465	    sect->compressionarg = 0x04;
1466	    sect->format = SANE_FRAME_G32D;
1467	    break;
1468	  case BH_COMP_G42D:
1469	    sect->compressiontype = 0x03;
1470	    sect->compressionarg = 0x00;
1471	    sect->format = SANE_FRAME_G42D;
1472	    break;
1473	  case BH_COMP_NONE:
1474	  default:
1475	    sect->compressiontype = 0x00;
1476	    sect->compressionarg = 0x00;
1477	    sect->format = SANE_FRAME_GRAY;
1478	    break;
1479	  }
1480
1481	DBG(3, "section_parse: converted '%s' (mm) to "
1482	    "%ldx%ld+%ld+%ld (thousandths) "
1483	    "flags=%02x compression=[%d,%d] frame=%s\n",
1484	    val,
1485	    sect->width, sect->length, sect->left, sect->top,
1486	    sect->flags,
1487	    sect->compressiontype, sect->compressionarg,
1488	    sane_strframe(sect->format));
1489
1490      } while (0); /* perform 'loop' once */
1491    }
1492
1493  return status;
1494}
1495
1496static SANE_Status
1497setup_sections (BH_Scanner *s, const char *val)
1498{
1499  SANE_Status status = SANE_STATUS_GOOD;
1500  SANE_Int sectnum = 0;
1501  char buf[255+1], *section;
1502
1503  DBG(3, "setup_sections called\n");
1504
1505  memset(s->sections, '\0', sizeof(s->sections));
1506  if (strlen(val) > sizeof(buf) - 1)
1507    {
1508      DBG(1, "setup_sections: option string too long\n");
1509      status = SANE_STATUS_INVAL;
1510    }
1511  else
1512    {
1513      strcpy(buf, val);
1514
1515      section = strtok(buf, ",");
1516      while (section != NULL && sectnum < NUM_SECTIONS)
1517	{
1518	  if (!allblank(section))
1519	    {
1520	      SANE_Int res = _OPT_VAL_WORD(s, OPT_RESOLUTION);
1521	      SANE_Int format =
1522		get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION));
1523
1524	      status = section_parse(section, &s->sections[sectnum],
1525				     res, format);
1526	      if (status != SANE_STATUS_GOOD)
1527		{
1528		  DBG(1,
1529		      "setup_sections: error parsing section `%s'\n",
1530		      section);
1531		  break;
1532		}
1533
1534	      sectnum++;
1535	    }
1536	  section += strlen(section) + 1;
1537	  if (section > buf + strlen(val)) break;
1538
1539	  section = strtok(section, ",");
1540	}
1541    }
1542  s->num_sections = sectnum;
1543
1544  return status;
1545}
1546
1547static SANE_Status
1548start_setup (BH_Scanner *s)
1549{
1550  SANE_Status status;
1551  SANE_Bool duplex;
1552  SANE_Int i, imagecnt;
1553  SANE_Byte batchmode;
1554
1555  DBG(3, "start_setup called\n");
1556
1557  duplex = _OPT_VAL_WORD(s, OPT_DUPLEX);
1558
1559  /* get the _SECTION option, parse it and fill in the sections */
1560  status = setup_sections(s, _OPT_VAL_STRING(s, OPT_SECTION));
1561  if (status != SANE_STATUS_GOOD)
1562    {
1563      DBG(1, "start_setup: setup_sections failed: %s\n",
1564	  sane_strstatus(status));
1565      return status;
1566    }
1567
1568  /* see whether we'll be decoding barcodes and
1569   * set the barcodes flag appropriately
1570   */
1571  if (s->search_bars[0] == 0)
1572    {
1573      s->barcodes = SANE_FALSE;
1574    }
1575  else
1576    {
1577      s->barcodes = SANE_TRUE;
1578    }
1579
1580  /* see whether we'll be handling icons (thumbnails)
1581   * set the icons flag appropriately
1582   */
1583  if (_OPT_VAL_WORD(s, OPT_ICON_WIDTH) >= 8 &&
1584      _OPT_VAL_WORD(s, OPT_ICON_LENGTH) >= 8)
1585    {
1586      s->icons = SANE_TRUE;
1587    }
1588  else
1589    {
1590      s->icons = SANE_FALSE;
1591    }
1592
1593
1594  /* calculate a new readlist for this 'batch' */
1595  s->readptr = s->readcnt = 0;
1596
1597  /* always read the front image */
1598  s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT;
1599
1600  /* read back page only if duplex is true */
1601  if (duplex == SANE_TRUE)
1602    {
1603      s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK;
1604    }
1605
1606  /* add image section reads to the readlist */
1607  for (i = 0; i < s->num_sections; i++)
1608    {
1609      SANE_Word flags = s->sections[i].flags;
1610
1611      if (flags & BH_SECTION_FRONT_IMAGE)
1612	s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT + i + 1;
1613      if (flags & BH_SECTION_BACK_IMAGE)
1614	s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK + i + 1;
1615    }
1616
1617
1618  /* icons (thumbnails) */
1619  if (s->icons)
1620    {
1621      s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_ICON;
1622      /* read back icon only if duplex is true */
1623      if (duplex == SANE_TRUE)
1624	{
1625	  s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_ICON;
1626	}
1627    }
1628
1629  /* NOTE: It is important that all of the image data comes before
1630   * the barcode/patchcode data.
1631   */
1632  /* barcodes */
1633  imagecnt = s->readcnt;
1634  if (s->barcodes)
1635    {
1636      if (s->num_sections == 0)
1637	{
1638	  /* we only decode the entire page(s) if there are no
1639	   * sections defined
1640	   */
1641	  s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_BARCODE;
1642	  /* read back barcode only if duplex is true */
1643	  if (duplex == SANE_TRUE)
1644	    {
1645	      s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_BARCODE;
1646	    }
1647	}
1648      else
1649	{
1650	  /* add barcode section reads to the readlist */
1651	  for (i = 0; i < s->num_sections; i++)
1652	    {
1653	      SANE_Word flags = s->sections[i].flags;
1654
1655	      if (flags & BH_SECTION_FRONT_BAR)
1656		s->readlist[s->readcnt++] =
1657		  BH_SCSI_READ_TYPE_FRONT_BARCODE + i + 1;
1658	      if (flags & BH_SECTION_BACK_BAR)
1659		s->readlist[s->readcnt++] =
1660		  BH_SCSI_READ_TYPE_BACK_BARCODE + i + 1;
1661	    }
1662	}
1663    }
1664
1665  /* patchcodes */
1666  if (s->patchcodes)
1667    {
1668      if (s->num_sections == 0)
1669	{
1670	  /* we only decode the entire page(s) if there are no
1671	   * sections defined
1672	   */
1673	  s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_PATCHCODE;
1674	  /* read back patchcode only if duplex is true */
1675	  if (duplex == SANE_TRUE)
1676	    {
1677	      s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_PATCHCODE;
1678	    }
1679	}
1680      else
1681	{
1682	  /* add patchcode section reads to the readlist */
1683	  for (i = 0; i < s->num_sections; i++)
1684	    {
1685	      SANE_Word flags = s->sections[i].flags;
1686
1687	      if (flags & BH_SECTION_FRONT_PATCH)
1688		s->readlist[s->readcnt++] =
1689		  BH_SCSI_READ_TYPE_FRONT_PATCHCODE + i + 1;
1690	      if (flags & BH_SECTION_BACK_PATCH)
1691		s->readlist[s->readcnt++] =
1692		  BH_SCSI_READ_TYPE_BACK_PATCHCODE + i + 1;
1693	    }
1694	}
1695    }
1696
1697  /* add the special item to the read list which transfers the barcode
1698   * file that's built as a result of processing barcode and patchcode
1699   * readitems.  NOTE: this one must be last!
1700   */
1701  if (s->readcnt > imagecnt)
1702    {
1703      s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_SENDBARFILE;
1704    }
1705
1706  if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE)
1707    {
1708      /* if batchmode is enabled, then call set_window to
1709       * abort the batch (even though there might not (and probably
1710       * isn't) a batch in progress).  This avoids a batch start error
1711       * in the case where a previous batch was not aborted.
1712       */
1713      DBG(5, "start_setup: calling set_window to abort batch\n");
1714      set_window(s, BH_BATCH_ABORT);
1715
1716      batchmode = BH_BATCH_ENABLE;
1717    }
1718  else
1719    {
1720      batchmode = BH_BATCH_DISABLE;
1721    }
1722
1723  DBG(5, "start_setup: duplex=%s, barcodes=%s, patchcodes=%s, "
1724      "icons=%s, batch=%s\n",
1725      (duplex == SANE_TRUE) ? "yes" : "no",
1726      (s->barcodes == SANE_TRUE) ? "yes" : "no",
1727      (s->patchcodes == SANE_TRUE) ? "yes" : "no",
1728      (s->icons == SANE_TRUE) ? "yes" : "no",
1729      (batchmode == BH_BATCH_ENABLE) ? "yes" : "no");
1730  DBG(5, "start_setup: sections=%d\n", s->num_sections);
1731  for (i = 0; i < s->num_sections; i++)
1732    {
1733      DBG(5, "start_setup:  "
1734	  "[%d] %lux%lu+%lu+%lu flags=%02x compression=[%d,%d]\n",
1735	  i+1,
1736	  s->sections[i].width, s->sections[i].length,
1737	  s->sections[i].left, s->sections[i].top,
1738	  s->sections[i].flags,
1739	  s->sections[i].compressiontype, s->sections[i].compressionarg);
1740    }
1741  DBG(5, "start_setup: read list length=%d\n", s->readcnt);
1742  for (i = 0; i < s->readcnt; i++)
1743    {
1744      DBG(5, "start_setup:  [%d] %s\n", i+1, print_read_type(s->readlist[i]));
1745    }
1746
1747  DBG(5, "start_setup: sending SET WINDOW\n");
1748  status = set_window(s, batchmode);
1749  if (status != SANE_STATUS_GOOD)
1750    {
1751      DBG(1, "start_setup: SET WINDOW failed: %s\n",
1752	   sane_strstatus(status));
1753      return status;
1754    }
1755
1756  DBG(5, "start_setup: sending mode_select_timeout\n");
1757  status = mode_select_timeout(s);
1758  if (status != SANE_STATUS_GOOD)
1759    {
1760      DBG(1, "start_setup: mode_select_timeout failed: %s\n",
1761	   sane_strstatus(status));
1762      return status;
1763    }
1764
1765  if (s->icons == SANE_TRUE)
1766    {
1767      DBG(5, "start_setup: sending mode_select_icon\n");
1768      status = mode_select_icon(s);
1769      if (status != SANE_STATUS_GOOD)
1770	{
1771	  DBG(1, "start_setup: mode_select_icon failed: %s\n",
1772	       sane_strstatus(status));
1773	  return status;
1774	}
1775    }
1776
1777  if (s->barcodes == SANE_TRUE)
1778    {
1779      DBG(5, "start_setup: sending mode_select_barcode_priority\n");
1780      status = mode_select_barcode_priority(s);
1781      if (status != SANE_STATUS_GOOD)
1782	{
1783	  DBG(1, "start_setup: mode_select_barcode_priority failed: %s\n",
1784	       sane_strstatus(status));
1785	  return status;
1786	}
1787
1788      DBG(5, "start_setup: sending mode_select_barcode_param1\n");
1789      status = mode_select_barcode_param1(s);
1790      if (status != SANE_STATUS_GOOD)
1791	{
1792	  DBG(1, "start_setup: mode_select_barcode_param1 failed: %s\n",
1793	       sane_strstatus(status));
1794	  return status;
1795	}
1796
1797      DBG(5, "start_setup: sending mode_select_barcode_param2\n");
1798      status = mode_select_barcode_param2(s);
1799      if (status != SANE_STATUS_GOOD)
1800	{
1801	  DBG(1, "start_setup: mode_select_barcode_param2 failed: %s\n",
1802	       sane_strstatus(status));
1803	  return status;
1804	}
1805
1806      DBG(5, "start_setup: sending mode_select_barcode_param3\n");
1807      status = mode_select_barcode_param3(s);
1808      if (status != SANE_STATUS_GOOD)
1809	{
1810	  DBG(1, "start_setup: mode_select_barcode_param3 failed: %s\n",
1811	       sane_strstatus(status));
1812	  return status;
1813	}
1814    }
1815
1816  return status;
1817}
1818
1819static SANE_Status
1820start_scan (BH_Scanner *s)
1821{
1822  static SANE_Byte cmd[8];
1823  SANE_Status status = SANE_STATUS_GOOD;
1824  SANE_Bool check_adf, duplex;
1825  DBG (3, "start_scan called\n");
1826
1827  /* SANE front ends will call this function between 'FRAMES'.
1828   * A single scan on the B&H may result in up to 56 different
1829   * things to read (20 are SANE image frames, 36 are non-SANE
1830   * data - decoded bar/patch codes).
1831   */
1832
1833  if (s->readcnt > 1 && s->scanning == SANE_TRUE)
1834    {
1835      DBG(3, "start_scan: any more items in the readlist?\n");
1836      /* we've been reading data from this scan, so we just
1837       * move on to the next item in the readlist without
1838       * starting a new scan.
1839       */
1840      s->readptr++;
1841      if (s->readptr < s->readcnt)
1842	{
1843	  SANE_Byte itemtype;
1844
1845	  for (; s->readptr < s->readcnt; s->readptr++)
1846	    {
1847
1848	      itemtype = s->readlist[s->readptr];
1849
1850	      DBG(3, "start_scan: advance readlist(%d, %d)\n",
1851		  s->readptr,
1852		  (int) itemtype);
1853
1854	      /* 'dance' by the non-SANE data streams
1855	       * like bar/patch code data
1856	       */
1857	      if (!BH_HAS_IMAGE_DATA(itemtype))
1858		{
1859		  int fd;
1860		  FILE *fp;
1861
1862		  strncpy(s->barfname, "/tmp/bhXXXXXX", sizeof(s->barfname));
1863		  s->barfname[sizeof(s->barfname)-1] = '\0';
1864		  fd = mkstemp(s->barfname);
1865
1866		  if (fd !=-1 && (fp = fdopen(fd, "w")) != NULL)
1867		    {
1868		      fprintf(fp, "<xml-stream>\n");
1869
1870		      for (;
1871			   s->readptr < s->readcnt &&
1872			     status == SANE_STATUS_GOOD;
1873			   s->readptr++)
1874			{
1875			  if (s->readlist[s->readptr] ==
1876			      BH_SCSI_READ_TYPE_SENDBARFILE) {
1877			    break;
1878			  }
1879			  status = read_barcode_data(s, fp);
1880			  if (status != SANE_STATUS_GOOD) break;
1881			}
1882
1883		      fprintf(fp, "</xml-stream>\n");
1884
1885		      /* close file; re-open for read(setting s->barfd) */
1886		      fclose(fp);
1887		      if ((s->barf = fopen(s->barfname, "r")) == NULL)
1888			{
1889			  DBG(1, "sane_start: error opening barfile `%s'\n",
1890			      s->barfname);
1891			  status = SANE_STATUS_IO_ERROR;
1892			}
1893		    }
1894		  else
1895		    {
1896		      DBG(1, "sane_start: error opening barfile `%s'\n",
1897			  s->barfname);
1898		      if (fd !=-1)
1899		        {
1900		          close(fd);
1901		          unlink(s->barfname);
1902		        }
1903		      status = SANE_STATUS_IO_ERROR;
1904		    }
1905		}
1906	      else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON ||
1907		       itemtype == BH_SCSI_READ_TYPE_BACK_ICON)
1908		{
1909		  /* read the icon header setting the iconwidth and iconlength
1910		   * to the actual values so get_parameters will have them.
1911		   * Subsequent calls to sane_read will get pure image data
1912		   * since the icon header has been consumed.
1913		   */
1914
1915		  status = read_icon_data(s);
1916		}
1917
1918	      if (status == SANE_STATUS_GOOD)
1919		{
1920		  /* update our parameters to reflect the new item */
1921		  status = get_parameters (s, 0);
1922		}
1923
1924	      if (status != SANE_STATUS_GOOD) s->scanning = SANE_FALSE;
1925
1926	      return status;
1927	    }
1928	  /* if we reach here, we're finished with the readlist and
1929	   * will drop through to start a new scan
1930	   */
1931	}
1932    }
1933
1934  s->readptr = 0;
1935
1936  check_adf = _OPT_VAL_WORD(s, OPT_CHECK_ADF);
1937  duplex = _OPT_VAL_WORD(s, OPT_DUPLEX);
1938
1939  memset (&cmd, 0, sizeof (cmd));
1940  cmd[0] = BH_SCSI_START_SCAN;
1941  cmd[4] = (duplex == SANE_TRUE) ? 2 : 1;
1942
1943  cmd[6] = 0;
1944  cmd[7] = 1;
1945
1946  if (check_adf)
1947    {
1948      status = object_position(s);
1949      if (status != SANE_STATUS_GOOD)
1950	{
1951	  DBG(3, "object_position: returned %d\n", status);
1952	  return status;
1953	}
1954    }
1955
1956  status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0);
1957  if (status == SANE_STATUS_GOOD)
1958    {
1959      s->scanning = SANE_TRUE;
1960
1961      /* update our parameters,
1962       * now that we're scanning we'll do a GET_WINDOW
1963       */
1964      status = get_parameters (s, 0);
1965      if (status != SANE_STATUS_GOOD)
1966	{
1967	  s->scanning = SANE_FALSE;
1968	}
1969    }
1970
1971  return status;
1972}
1973
1974/* a sensible sense handler, courtesy of Franck;
1975   arg is a pointer to the associated BH_Scanner structure */
1976static SANE_Status
1977sense_handler (int scsi_fd, u_char *result, void *arg)
1978{
1979  BH_Scanner *s = (BH_Scanner *) arg;
1980  u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData;
1981  u_long InvalidBytes;
1982  char *sense_str = "", *as_str = "";
1983  SANE_Int i;
1984  SANE_Status status = SANE_STATUS_INVAL;
1985  SANE_Char print_sense[(16 * 3) + 1];
1986
1987  (void) scsi_fd; /* get rid of compiler warning */
1988  ErrorCode = result[0] & 0x7F;
1989  ValidData = (result[0] & 0x80) != 0;
1990  sense = result[2] & 0x0f; /* Key */
1991  asc = result[12]; /* Code */
1992  ascq = result[13]; /* Qual */
1993  EOM = (result[2] & 0x40) != 0; /* End Of Media */
1994  ILI = (result[2] & 0x20) != 0; /* Invalid Length Indicator */
1995  InvalidBytes = ValidData ? _4btol(&result[3]) : 0;
1996
1997  DBG(3, "sense_handler: result=%x, sense=%x, asc=%x, ascq=%x\n",
1998      result[0], sense, asc, ascq);
1999  DBG(3, "sense_handler: ErrorCode %02x ValidData: %d "
2000      "EOM: %d ILI: %d InvalidBytes: %lu\n",
2001      ErrorCode, ValidData, EOM, ILI, InvalidBytes);
2002
2003  memset(print_sense, '\0', sizeof(print_sense));
2004  for (i = 0; i < 16; i++)
2005    {
2006      sprintf(print_sense + strlen(print_sense), "%02x ", result[i]);
2007    }
2008  DBG(5, "sense_handler: sense=%s\n", print_sense);
2009
2010  if (ErrorCode != 0x70 && ErrorCode != 0x71)
2011    {
2012      DBG (3, "sense_handler: error code is invalid.\n");
2013      return SANE_STATUS_IO_ERROR;	/* error code is invalid */
2014    }
2015
2016  /* handle each sense key;
2017   * RSC supports 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0B
2018   */
2019  switch (sense)
2020    {
2021    case 0x00:
2022      /* no sense */
2023      sense_str = "No sense.";
2024      status = SANE_STATUS_GOOD;
2025      if (ILI && asc == 0x00 && ascq == 0x05)
2026	{
2027	  /* from read_data function */
2028	  as_str = "ILI bit is set.";
2029	  if (s != NULL)
2030	    {
2031	      s->InvalidBytes = InvalidBytes;
2032	    }
2033	  status = SANE_STATUS_GOOD;
2034	}
2035      else if (EOM && asc == 0x00 && ascq == 0x02)
2036	{
2037	  /* from adfStatus or startScan function */
2038	  as_str = "Out of paper in the hopper.";
2039	  status = SANE_STATUS_NO_DOCS;
2040	}
2041      else if (EOM)
2042	{
2043	  /* from adfStatus or startScan function */
2044	  as_str = "Out of paper in the hopper.";
2045	  status = SANE_STATUS_NO_DOCS;
2046	}
2047      break;
2048    case 0x01:
2049      /* recovered error */
2050      sense_str = "Recovered error.";
2051      status = SANE_STATUS_GOOD;
2052      break;
2053    case 0x02:
2054      /* not ready */
2055      sense_str = "Not ready.";
2056      status = SANE_STATUS_DEVICE_BUSY;
2057      if (asc == 0x40 && ascq == 0x01)
2058	{
2059	  as_str = "P.O.D. error: Scanner not found.";
2060	  status = SANE_STATUS_INVAL;
2061	}
2062      else if (asc == 0x40 && ascq == 0x02)
2063	{
2064	  as_str = "P.O.D. error: Scanner not ready(paper in transport).";
2065	  status = SANE_STATUS_DEVICE_BUSY;
2066	}
2067      else if (asc == 0x40 && ascq == 0x03)
2068	{
2069	  as_str = "P.O.D. error: Unknown scanner.";
2070	  status = SANE_STATUS_INVAL;
2071	}
2072      break;
2073    case 0x03:
2074      /* medium error */
2075      sense_str = "Medium error.";
2076      status = SANE_STATUS_IO_ERROR;
2077      if (asc == 0x00 && ascq == 0x00)
2078	{
2079	  as_str = "Scanner error: paper jam detected.";
2080	  status = SANE_STATUS_JAMMED;
2081	}
2082      break;
2083    case 0x04:
2084      /* hardware error */
2085      sense_str = "Hardware error.";
2086      status = SANE_STATUS_IO_ERROR;
2087      if (asc == 0x60 && ascq == 0x00)
2088	{
2089	  as_str = "Scanner error: illumination lamps failure.";
2090	  status = SANE_STATUS_IO_ERROR;
2091	}
2092      else if (asc == 0x80 && ascq == 0x03)
2093	{
2094	  as_str = "Communication error between RSC and scanner.";
2095	  status = SANE_STATUS_IO_ERROR;
2096	}
2097      else if (asc == 0x80 && ascq == 0x06)
2098	{
2099	  as_str = "Scanner error: page detected but lamps are off.";
2100	  status = SANE_STATUS_IO_ERROR;
2101	}
2102      else if (asc == 0x80 && ascq == 0x07)
2103	{
2104	  as_str = "Scanner error: camera white level problem.";
2105	  status = SANE_STATUS_IO_ERROR;
2106	}
2107      else if (asc == 0x80 && ascq == 0x08)
2108	{
2109	  /* could be caught from start_scan or read_data */
2110	  /* stop button pressed */
2111	  as_str = "Scanner error: operator pressed the Stop key.";
2112	  status = SANE_STATUS_NO_DOCS;
2113	}
2114      else if (asc == 0x80 && ascq == 0x12)
2115	{
2116	  as_str = "Scanner error: transport motor failure.";
2117	  status = SANE_STATUS_IO_ERROR;
2118	}
2119      else if (asc == 0x80 && ascq == 0x15)
2120	{
2121	  as_str = "Scanner error: device / page sensor(s) bouncing.";
2122	  status = SANE_STATUS_IO_ERROR;
2123	}
2124      else if (asc == 0x80 && ascq == 0x16)
2125	{
2126	  as_str = "Scanner error: feeder is not attached.";
2127	  status = SANE_STATUS_IO_ERROR;
2128	}
2129      else if (asc == 0x80 && ascq == 0x18)
2130	{
2131	  as_str = "Scanner error: logic system general failure.";
2132	  status = SANE_STATUS_IO_ERROR;
2133	}
2134      else if (asc == 0x80 && ascq == 0x34)
2135	{
2136	  as_str = "Scanner error: no dual logic communication.";
2137	  status = SANE_STATUS_IO_ERROR;
2138	}
2139      break;
2140    case 0x05:
2141      /* illegal request */
2142      sense_str = "Illegal request.";
2143      status = SANE_STATUS_INVAL;
2144      if (asc == 0x1a && ascq == 0x00)
2145	{
2146	  as_str = "Parameter list length error.";
2147	  status = SANE_STATUS_INVAL;
2148	}
2149      else if (asc == 0x20 && ascq == 0x00)
2150	{
2151	  as_str = "Invalid command operation code.";
2152	  status = SANE_STATUS_INVAL;
2153	}
2154      else if (asc == 0x24 && ascq == 0x00)
2155	{
2156	  /* caught from object_position (via reverse engineering) */
2157	  /* Not supported? */
2158	  as_str = "Invalid field in CDB.";
2159	  status = SANE_STATUS_INVAL;
2160	}
2161      else if (asc == 0x25 && ascq == 0x00)
2162	{
2163	  as_str = "Unsupported LUN.";
2164	  status = SANE_STATUS_INVAL;
2165	}
2166      else if (asc == 0x26 && ascq == 0x00)
2167	{
2168	  /* caught from mode_select (as well as others) */
2169	  /* Bar/Patch code detection support not installed */
2170	  /* See Appendix A, Section A.5 */
2171	  as_str = "Invalid field in parameter list.";
2172	  status = SANE_STATUS_INVAL;
2173	}
2174      else if (asc == 0x2c && ascq == 0x00)
2175	{
2176	  /* we were getting this in read_data during the time
2177	     that the ADF was misbehaving.  Hopefully we will
2178	     not see it anymore.
2179	  */
2180	  as_str = "Command out of sequence.";
2181	  status = SANE_STATUS_INVAL;
2182	}
2183      else if (asc == 0x2c && ascq == 0x01)
2184	{
2185	  as_str = "Too many windows defined.";
2186	  status = SANE_STATUS_INVAL;
2187	}
2188      else if (asc == 0x2c && ascq == 0x02)
2189	{
2190	  as_str = "Batch start error.";
2191	  status = SANE_STATUS_INVAL;
2192	}
2193      else if (asc == 0x2c && ascq == 0x03)
2194	{
2195	  as_str = "Batch abort error.";
2196	  status = SANE_STATUS_INVAL;
2197	}
2198      else if (asc == 0x3d && ascq == 0x00)
2199	{
2200	  as_str = "Invalid bits in IDENTIFY message.";
2201	  status = SANE_STATUS_INVAL;
2202	}
2203      break;
2204    case 0x06:
2205      /* unit attention */
2206      sense_str = "Unit attention.";
2207      status = SANE_STATUS_IO_ERROR;
2208      if (asc == 0x04 && ascq == 0x01)
2209	{
2210	  as_str = "Reset detected, LUN is becoming ready.";
2211	  status = SANE_STATUS_DEVICE_BUSY;
2212	}
2213      break;
2214    case 0x07:
2215      /* data protect */
2216      sense_str = "Data protect.";
2217      status = SANE_STATUS_IO_ERROR;
2218      break;
2219    case 0x08:
2220      /* blank check */
2221      sense_str = "Blank check.";
2222      status = SANE_STATUS_IO_ERROR;
2223      break;
2224    case 0x09:
2225      /* vendor specific */
2226      sense_str = "Vendor specific.";
2227      status = SANE_STATUS_IO_ERROR;
2228      break;
2229    case 0x0A:
2230      /* copy aborted */
2231      sense_str = "Copy aborted.";
2232      status = SANE_STATUS_IO_ERROR;
2233      break;
2234    case 0x0B:
2235      /* aborted command */
2236      sense_str = "Aborted command.";
2237      status = SANE_STATUS_IO_ERROR;
2238      if (asc == 0x00 && ascq == 0x00)
2239	{
2240	  as_str = "Aborted command (unspecified error).";
2241	  status = SANE_STATUS_IO_ERROR;
2242	}
2243      else if (asc == 0x08 && ascq == 0x01)
2244	{
2245	  /* caught from start_scan */
2246	  /* manual feed timeout */
2247	  as_str = "SCSI Time-out, paper Time-out (SCAN command).";
2248	  status = SANE_STATUS_NO_DOCS;
2249	}
2250      else if (asc == 0x47 && ascq == 0x00)
2251	{
2252	  as_str = "SCSI parity error.";
2253	  status = SANE_STATUS_IO_ERROR;
2254	}
2255      else if (asc == 0x80 && ascq == 0x00)
2256	{
2257	  as_str = "Aborted command due to memory error.";
2258	  status = SANE_STATUS_IO_ERROR;
2259	}
2260      else if (asc == 0x80 && ascq == 0x01)
2261	{
2262	  /* caught from read_data */
2263	  /* section border error; border is outside the main window */
2264	  /* See Appendix A, Section A.4 */
2265	  as_str = "Section Read error (out of border).";
2266	  status = SANE_STATUS_INVAL;
2267	}
2268      else if (asc == 0x80 && ascq == 0x02)
2269	{
2270	  /* caught from read_data */
2271	  /* No code found; no barcode data is found */
2272	  /* See Appendix A, Section A.5 */
2273	  s->barcode_not_found = SANE_TRUE;
2274	  as_str = "No Bar/Patch Code found.";
2275	  status = SANE_STATUS_GOOD;
2276	}
2277      else if (asc == 0x80 && ascq == 0x03)
2278	{
2279	  as_str = "Icon Read error (out of border).";
2280	  status = SANE_STATUS_INVAL;
2281	}
2282      break;
2283    case 0x0C:
2284      /* equal */
2285      sense_str = "Equal.";
2286      status = SANE_STATUS_IO_ERROR;
2287      break;
2288    case 0x0D:
2289      /* volume overflow */
2290      sense_str = "Volume overflow.";
2291      status = SANE_STATUS_IO_ERROR;
2292      break;
2293    case 0x0E:
2294      /* miscompare */
2295      sense_str = "Miscompare.";
2296      status = SANE_STATUS_IO_ERROR;
2297      break;
2298    case 0x0F:
2299      /* reserved */
2300      sense_str = "Reserved.";
2301      status = SANE_STATUS_IO_ERROR;
2302      break;
2303    default:
2304      sense_str = "Unhandled case.";
2305      status = SANE_STATUS_IO_ERROR;
2306      break;
2307    }
2308
2309  DBG(3, "sense_handler: '%s' '%s' return:%d\n",
2310      sense_str, as_str, status);
2311
2312  return status;
2313}
2314
2315static SANE_Status
2316init_options (BH_Scanner * s)
2317{
2318  int i;
2319  DBG (3, "init_options called\n");
2320
2321  memset (s->opt, 0, sizeof (s->opt));
2322  memset (s->val, 0, sizeof (s->val));
2323
2324  for (i = 0; i < NUM_OPTIONS; ++i)
2325    {
2326      s->opt[i].size = sizeof (SANE_Word);
2327      s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
2328    }
2329
2330  s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
2331  s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
2332  s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
2333  s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
2334  s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
2335
2336  /* "Scan Mode" group: */
2337  s->opt[OPT_MODE_GROUP].name = "";
2338  s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP;
2339  s->opt[OPT_MODE_GROUP].desc = "";
2340  s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
2341  s->opt[OPT_MODE_GROUP].cap = 0;
2342  s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2343
2344  /* Preview: */
2345  s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
2346  s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
2347  s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
2348  s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
2349  s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
2350  s->val[OPT_PREVIEW].w = 0;
2351
2352  /* Inquiry */
2353  s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY;
2354  s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY;
2355  s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY;
2356  s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING;
2357  s->opt[OPT_INQUIRY].size = sizeof(inquiry_data);
2358  s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE;
2359  s->val[OPT_INQUIRY].s = strdup(inquiry_data);
2360  s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT;
2361
2362  /* scan mode */
2363  s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE;
2364  s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE;
2365  s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE;
2366  s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING;
2367  s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_list);
2368  s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2369  s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_list;
2370  s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]);
2371
2372  /* Standard resolutions */
2373  s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
2374  s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
2375  s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
2376  s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
2377  s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
2378  s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
2379  s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList;
2380  s->val[OPT_RESOLUTION].w = s->hw->info.res_default;
2381
2382  /* compression */
2383  s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION;
2384  s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION;
2385  s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION;
2386  s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING;
2387  s->opt[OPT_COMPRESSION].size = max_string_size (compression_list);
2388  s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2389  s->opt[OPT_COMPRESSION].constraint.string_list = compression_list;
2390  s->val[OPT_COMPRESSION].s = strdup (compression_list[0]);
2391
2392  if (s->hw->info.colorHalftone == SANE_FALSE)
2393    {
2394      s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_min_list);
2395      s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_min_list;
2396    }
2397
2398  if (s->hw->info.comprG3_1D == SANE_FALSE ||
2399      s->hw->info.comprG3_2D == SANE_FALSE ||
2400      s->hw->info.comprG4 == SANE_FALSE)
2401    {
2402      s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE;
2403    }
2404
2405  /* "Geometry" group: */
2406  s->opt[OPT_GEOMETRY_GROUP].name = "";
2407  s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP;
2408  s->opt[OPT_GEOMETRY_GROUP].desc = "";
2409  s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
2410  s->opt[OPT_GEOMETRY_GROUP].cap = 0;
2411  s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2412
2413  /* Autoborder: */
2414  s->opt[OPT_AUTOBORDER].name = SANE_NAME_AUTOBORDER;
2415  s->opt[OPT_AUTOBORDER].title = SANE_TITLE_AUTOBORDER;
2416  s->opt[OPT_AUTOBORDER].desc = SANE_DESC_AUTOBORDER;
2417  s->opt[OPT_AUTOBORDER].type = SANE_TYPE_BOOL;
2418  s->opt[OPT_AUTOBORDER].constraint_type = SANE_CONSTRAINT_NONE;
2419  s->val[OPT_AUTOBORDER].w = s->hw->info.autoborder_default;
2420
2421  /* Paper Size */
2422  s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE;
2423  s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE;
2424  s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE;
2425  s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING;
2426  s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list);
2427  s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2428  s->opt[OPT_PAPER_SIZE].constraint.string_list = paper_list;
2429  s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]);
2430
2431  /* rotation */
2432  s->opt[OPT_ROTATION].name = SANE_NAME_ROTATION;
2433  s->opt[OPT_ROTATION].title = SANE_TITLE_ROTATION;
2434  s->opt[OPT_ROTATION].desc = SANE_DESC_ROTATION;
2435  s->opt[OPT_ROTATION].type = SANE_TYPE_STRING;
2436  s->opt[OPT_ROTATION].size = max_string_size (rotation_list);
2437  s->opt[OPT_ROTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2438  s->opt[OPT_ROTATION].constraint.string_list = rotation_list;
2439  s->val[OPT_ROTATION].s = strdup (rotation_list[0]);
2440
2441  /* Deskew: */
2442  s->opt[OPT_DESKEW].name = SANE_NAME_DESKEW;
2443  s->opt[OPT_DESKEW].title = SANE_TITLE_DESKEW;
2444  s->opt[OPT_DESKEW].desc = SANE_DESC_DESKEW;
2445  s->opt[OPT_DESKEW].type = SANE_TYPE_BOOL;
2446  s->opt[OPT_DESKEW].constraint_type = SANE_CONSTRAINT_NONE;
2447  s->val[OPT_DESKEW].w =  s->hw->info.deskew_default;
2448
2449  /* top-left x */
2450  s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
2451  s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
2452  s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
2453  s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
2454  s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
2455  s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
2456  s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range);
2457  s->val[OPT_TL_X].w = SANE_FIX(0.0);
2458
2459  /* top-left y */
2460  s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
2461  s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
2462  s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
2463  s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
2464  s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
2465  s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2466  s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range);
2467  s->val[OPT_TL_Y].w = SANE_FIX(0.0);
2468
2469  /* bottom-right x */
2470  s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
2471  s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
2472  s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
2473  s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
2474  s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
2475  s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
2476  s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range);
2477  s->val[OPT_BR_X].w = s->hw->info.x_range.max;
2478
2479  /* bottom-right y */
2480  s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
2481  s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
2482  s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
2483  s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
2484  s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
2485  s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
2486  s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range);
2487  s->val[OPT_BR_Y].w = s->hw->info.y_range.max;
2488
2489  if (s->hw->info.canBorderRecog == SANE_FALSE)
2490    {
2491      s->opt[OPT_AUTOBORDER].cap |= SANE_CAP_INACTIVE;
2492    }
2493
2494  /* "Feeder" group: */
2495  s->opt[OPT_FEEDER_GROUP].name = "";
2496  s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP;
2497  s->opt[OPT_FEEDER_GROUP].desc = "";
2498  s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP;
2499  s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED;
2500  s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2501
2502  /* scan source */
2503  s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE;
2504  s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
2505  s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
2506  s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING;
2507  s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list);
2508  s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2509  s->opt[OPT_SCAN_SOURCE].constraint.string_list = scan_source_list;
2510  s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]);
2511
2512  /* Batch: */
2513  s->opt[OPT_BATCH].name = SANE_NAME_BATCH;
2514  s->opt[OPT_BATCH].title = SANE_TITLE_BATCH;
2515  s->opt[OPT_BATCH].desc = SANE_DESC_BATCH;
2516  s->opt[OPT_BATCH].type = SANE_TYPE_BOOL;
2517  s->opt[OPT_BATCH].constraint_type = SANE_CONSTRAINT_NONE;
2518  s->val[OPT_BATCH].w =  s->hw->info.batch_default;
2519
2520  /* Check ADF: */
2521  s->opt[OPT_CHECK_ADF].name = SANE_NAME_CHECK_ADF;
2522  s->opt[OPT_CHECK_ADF].title = SANE_TITLE_CHECK_ADF;
2523  s->opt[OPT_CHECK_ADF].desc = SANE_DESC_CHECK_ADF;
2524  s->opt[OPT_CHECK_ADF].type = SANE_TYPE_BOOL;
2525  s->opt[OPT_CHECK_ADF].constraint_type = SANE_CONSTRAINT_NONE;
2526  s->val[OPT_CHECK_ADF].w =  s->hw->info.check_adf_default;
2527
2528  /* Duplex: */
2529  s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX;
2530  s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX;
2531  s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX;
2532  s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL;
2533  s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE;
2534  s->val[OPT_DUPLEX].w = s->hw->info.duplex_default;
2535
2536  /* timeout adf */
2537  s->opt[OPT_TIMEOUT_ADF].name = SANE_NAME_TIMEOUT_ADF;
2538  s->opt[OPT_TIMEOUT_ADF].title = SANE_TITLE_TIMEOUT_ADF;
2539  s->opt[OPT_TIMEOUT_ADF].desc = SANE_DESC_TIMEOUT_ADF;
2540  s->opt[OPT_TIMEOUT_ADF].type = SANE_TYPE_INT;
2541  s->opt[OPT_TIMEOUT_ADF].unit = SANE_UNIT_NONE;
2542  s->opt[OPT_TIMEOUT_ADF].constraint_type = SANE_CONSTRAINT_RANGE;
2543  s->opt[OPT_TIMEOUT_ADF].constraint.range = &u8_range;
2544  s->val[OPT_TIMEOUT_ADF].w =  s->hw->info.timeout_adf_default;
2545
2546  /* timeout manual */
2547  s->opt[OPT_TIMEOUT_MANUAL].name = SANE_NAME_TIMEOUT_MANUAL;
2548  s->opt[OPT_TIMEOUT_MANUAL].title = SANE_TITLE_TIMEOUT_MANUAL;
2549  s->opt[OPT_TIMEOUT_MANUAL].desc = SANE_DESC_TIMEOUT_MANUAL;
2550  s->opt[OPT_TIMEOUT_MANUAL].type = SANE_TYPE_INT;
2551  s->opt[OPT_TIMEOUT_MANUAL].unit = SANE_UNIT_NONE;
2552  s->opt[OPT_TIMEOUT_MANUAL].constraint_type = SANE_CONSTRAINT_RANGE;
2553  s->opt[OPT_TIMEOUT_MANUAL].constraint.range = &u8_range;
2554  s->val[OPT_TIMEOUT_MANUAL].w =  s->hw->info.timeout_manual_default;
2555
2556  if (s->hw->info.canCheckADF == SANE_FALSE)
2557    {
2558      s->opt[OPT_CHECK_ADF].cap |= SANE_CAP_INACTIVE;
2559    }
2560
2561  if (s->hw->info.canDuplex == SANE_FALSE)
2562    {
2563      s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE;
2564    }
2565
2566  if (s->hw->info.canADF == SANE_FALSE)
2567    {
2568      s->opt[OPT_TIMEOUT_ADF].cap |= SANE_CAP_INACTIVE;
2569    }
2570
2571  /* "Enhancement" group: */
2572  s->opt[OPT_ENHANCEMENT_GROUP].name = "";
2573  s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP;
2574  s->opt[OPT_ENHANCEMENT_GROUP].desc = "";
2575  s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
2576  s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED;
2577  s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2578
2579  /* Control Panel: */
2580  s->opt[OPT_CONTROL_PANEL].name = SANE_NAME_CONTROL_PANEL;
2581  s->opt[OPT_CONTROL_PANEL].title = SANE_TITLE_CONTROL_PANEL;
2582  s->opt[OPT_CONTROL_PANEL].desc = SANE_DESC_CONTROL_PANEL;
2583  s->opt[OPT_CONTROL_PANEL].type = SANE_TYPE_BOOL;
2584  s->opt[OPT_CONTROL_PANEL].constraint_type = SANE_CONSTRAINT_NONE;
2585  s->val[OPT_CONTROL_PANEL].w =  s->hw->info.control_panel_default;
2586
2587  /* Ace_Function */
2588  s->opt[OPT_ACE_FUNCTION].name = SANE_NAME_ACE_FUNCTION;
2589  s->opt[OPT_ACE_FUNCTION].title = SANE_TITLE_ACE_FUNCTION;
2590  s->opt[OPT_ACE_FUNCTION].desc = SANE_DESC_ACE_FUNCTION;
2591  s->opt[OPT_ACE_FUNCTION].type = SANE_TYPE_INT;
2592  s->opt[OPT_ACE_FUNCTION].unit = SANE_UNIT_NONE;
2593  s->opt[OPT_ACE_FUNCTION].constraint_type = SANE_CONSTRAINT_RANGE;
2594  s->opt[OPT_ACE_FUNCTION].constraint.range = &ace_function_range;
2595  s->val[OPT_ACE_FUNCTION].w = 0;
2596
2597  /* Ace_Sensitivity */
2598  s->opt[OPT_ACE_SENSITIVITY].name = SANE_NAME_ACE_SENSITIVITY;
2599  s->opt[OPT_ACE_SENSITIVITY].title = SANE_TITLE_ACE_SENSITIVITY;
2600  s->opt[OPT_ACE_SENSITIVITY].desc = SANE_DESC_ACE_SENSITIVITY;
2601  s->opt[OPT_ACE_SENSITIVITY].type = SANE_TYPE_INT;
2602  s->opt[OPT_ACE_SENSITIVITY].unit = SANE_UNIT_NONE;
2603  s->opt[OPT_ACE_SENSITIVITY].constraint_type = SANE_CONSTRAINT_RANGE;
2604  s->opt[OPT_ACE_SENSITIVITY].constraint.range = &ace_sensitivity_range;
2605  s->val[OPT_ACE_SENSITIVITY].w = 4;
2606
2607  /* Brightness */
2608  s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
2609  s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
2610  s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
2611  s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT;
2612  s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE;
2613  s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
2614  s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range;
2615  s->val[OPT_BRIGHTNESS].w = 0;
2616
2617  /* Threshold */
2618  s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
2619  s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
2620  s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
2621  s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
2622  s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE;
2623  s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
2624  s->opt[OPT_THRESHOLD].constraint.range = &u8_range;
2625  s->val[OPT_THRESHOLD].w = 0;
2626
2627  /* Contrast */
2628  s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
2629  s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
2630  s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
2631  s->opt[OPT_CONTRAST].type = SANE_TYPE_INT;
2632  s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE;
2633  s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2634  s->opt[OPT_CONTRAST].constraint.range = &u8_range;
2635  s->val[OPT_CONTRAST].w = 0;
2636
2637  /* Negative: */
2638  s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
2639  s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
2640  s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
2641  s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
2642  s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
2643  s->val[OPT_NEGATIVE].w = SANE_FALSE;
2644
2645  /* Contrast is not used in any case; why did we add it? */
2646  s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
2647  if (s->hw->info.control_panel_default == SANE_TRUE)
2648    {
2649      s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE;
2650      s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE;
2651      s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2652      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2653    }
2654  else if (s->hw->info.canACE == SANE_FALSE)
2655    {
2656      s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE;
2657      s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE;
2658    }
2659  else
2660    {
2661      s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
2662      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
2663    }
2664
2665  /* "ICON" group: */
2666  s->opt[OPT_ICON_GROUP].name = "";
2667  s->opt[OPT_ICON_GROUP].title = SANE_TITLE_ICON_GROUP;
2668  s->opt[OPT_ICON_GROUP].desc = "";
2669  s->opt[OPT_ICON_GROUP].type = SANE_TYPE_GROUP;
2670  s->opt[OPT_ICON_GROUP].cap = SANE_CAP_ADVANCED;
2671  s->opt[OPT_ICON_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2672
2673  /* Icon_Width */
2674  s->opt[OPT_ICON_WIDTH].name = SANE_NAME_ICON_WIDTH;
2675  s->opt[OPT_ICON_WIDTH].title = SANE_TITLE_ICON_WIDTH;
2676  s->opt[OPT_ICON_WIDTH].desc = SANE_DESC_ICON_WIDTH;
2677  s->opt[OPT_ICON_WIDTH].type = SANE_TYPE_INT;
2678  s->opt[OPT_ICON_WIDTH].unit = SANE_UNIT_PIXEL;
2679  s->opt[OPT_ICON_WIDTH].constraint_type = SANE_CONSTRAINT_RANGE;
2680  s->opt[OPT_ICON_WIDTH].constraint.range = &icon_range;
2681  s->val[OPT_ICON_WIDTH].w = 0;
2682
2683  /* Icon_Length */
2684  s->opt[OPT_ICON_LENGTH].name = SANE_NAME_ICON_LENGTH;
2685  s->opt[OPT_ICON_LENGTH].title = SANE_TITLE_ICON_LENGTH;
2686  s->opt[OPT_ICON_LENGTH].desc = SANE_DESC_ICON_LENGTH;
2687  s->opt[OPT_ICON_LENGTH].type = SANE_TYPE_INT;
2688  s->opt[OPT_ICON_LENGTH].unit = SANE_UNIT_PIXEL;
2689  s->opt[OPT_ICON_LENGTH].constraint_type = SANE_CONSTRAINT_RANGE;
2690  s->opt[OPT_ICON_LENGTH].constraint.range = &icon_range;
2691  s->val[OPT_ICON_LENGTH].w = 0;
2692
2693  if (s->hw->info.canIcon == SANE_FALSE)
2694    {
2695      s->opt[OPT_ICON_GROUP].cap |= SANE_CAP_INACTIVE;
2696      s->opt[OPT_ICON_WIDTH].cap |= SANE_CAP_INACTIVE;
2697      s->opt[OPT_ICON_LENGTH].cap |= SANE_CAP_INACTIVE;
2698    }
2699
2700  /* "Barcode" group: */
2701  s->opt[OPT_BARCODE_GROUP].name = "";
2702  s->opt[OPT_BARCODE_GROUP].title = SANE_TITLE_BARCODE_GROUP;
2703  s->opt[OPT_BARCODE_GROUP].desc = "";
2704  s->opt[OPT_BARCODE_GROUP].type = SANE_TYPE_GROUP;
2705  s->opt[OPT_BARCODE_GROUP].cap = SANE_CAP_ADVANCED;
2706  s->opt[OPT_BARCODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
2707
2708  /* Add <name> to barcode search priority. */
2709  s->opt[OPT_BARCODE_SEARCH_BAR].name = SANE_NAME_BARCODE_SEARCH_BAR;
2710  s->opt[OPT_BARCODE_SEARCH_BAR].title = SANE_TITLE_BARCODE_SEARCH_BAR;
2711  s->opt[OPT_BARCODE_SEARCH_BAR].desc = SANE_DESC_BARCODE_SEARCH_BAR;
2712  s->opt[OPT_BARCODE_SEARCH_BAR].type = SANE_TYPE_STRING;
2713  s->opt[OPT_BARCODE_SEARCH_BAR].unit = SANE_UNIT_NONE;
2714  s->opt[OPT_BARCODE_SEARCH_BAR].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2715  s->opt[OPT_BARCODE_SEARCH_BAR].constraint.string_list = barcode_search_bar_list;
2716  s->opt[OPT_BARCODE_SEARCH_BAR].size = max_string_size (barcode_search_bar_list);
2717  s->val[OPT_BARCODE_SEARCH_BAR].s = strdup (barcode_search_bar_list[0]);
2718
2719  /* Barcode search count (1-7, default 1). */
2720  s->opt[OPT_BARCODE_SEARCH_COUNT].name = SANE_NAME_BARCODE_SEARCH_COUNT;
2721  s->opt[OPT_BARCODE_SEARCH_COUNT].title = SANE_TITLE_BARCODE_SEARCH_COUNT;
2722  s->opt[OPT_BARCODE_SEARCH_COUNT].desc = SANE_DESC_BARCODE_SEARCH_COUNT;
2723  s->opt[OPT_BARCODE_SEARCH_COUNT].type = SANE_TYPE_INT;
2724  s->opt[OPT_BARCODE_SEARCH_COUNT].unit = SANE_UNIT_NONE;
2725  s->opt[OPT_BARCODE_SEARCH_COUNT].constraint_type = SANE_CONSTRAINT_RANGE;
2726  s->opt[OPT_BARCODE_SEARCH_COUNT].constraint.range = &barcode_search_count_range;
2727  s->val[OPT_BARCODE_SEARCH_COUNT].w =  3;
2728
2729  /* Barcode search mode. horiz-vert, horizontal, vertical, vert-horiz */
2730  s->opt[OPT_BARCODE_SEARCH_MODE].name = SANE_NAME_BARCODE_SEARCH_MODE;
2731  s->opt[OPT_BARCODE_SEARCH_MODE].title = SANE_TITLE_BARCODE_SEARCH_MODE;
2732  s->opt[OPT_BARCODE_SEARCH_MODE].desc = SANE_DESC_BARCODE_SEARCH_MODE;
2733  s->opt[OPT_BARCODE_SEARCH_MODE].type = SANE_TYPE_STRING;
2734  s->opt[OPT_BARCODE_SEARCH_MODE].size = max_string_size (barcode_search_mode_list);
2735  s->opt[OPT_BARCODE_SEARCH_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
2736  s->opt[OPT_BARCODE_SEARCH_MODE].constraint.string_list = barcode_search_mode_list;
2737  s->val[OPT_BARCODE_SEARCH_MODE].s = strdup(barcode_search_mode_list[0]);
2738
2739  /* Patch code min height (def=5mm) */
2740  s->opt[OPT_BARCODE_HMIN].name = SANE_NAME_BARCODE_HMIN;
2741  s->opt[OPT_BARCODE_HMIN].title = SANE_TITLE_BARCODE_HMIN;
2742  s->opt[OPT_BARCODE_HMIN].desc = SANE_DESC_BARCODE_HMIN;
2743  s->opt[OPT_BARCODE_HMIN].type = SANE_TYPE_INT;
2744  s->opt[OPT_BARCODE_HMIN].unit = SANE_UNIT_MM;
2745  s->opt[OPT_BARCODE_HMIN].constraint_type = SANE_CONSTRAINT_RANGE;
2746  s->opt[OPT_BARCODE_HMIN].constraint.range = &barcode_hmin_range;
2747  s->val[OPT_BARCODE_HMIN].w =  5;
2748
2749  /* Barcode search timeout in ms (20-65535,default is 10000). */
2750  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].name = SANE_NAME_BARCODE_SEARCH_TIMEOUT;
2751  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].title = SANE_TITLE_BARCODE_SEARCH_TIMEOUT;
2752  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].desc = SANE_DESC_BARCODE_SEARCH_TIMEOUT;
2753  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].type = SANE_TYPE_INT;
2754  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].unit = SANE_UNIT_MICROSECOND;
2755  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE;
2756  s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint.range = &barcode_search_timeout_range;
2757  s->val[OPT_BARCODE_SEARCH_TIMEOUT].w =  10000;
2758
2759  /* Specify image sections and functions */
2760  s->opt[OPT_SECTION].name = SANE_NAME_SECTION;
2761  s->opt[OPT_SECTION].title = SANE_TITLE_SECTION;
2762  s->opt[OPT_SECTION].desc = SANE_DESC_SECTION;
2763  s->opt[OPT_SECTION].type = SANE_TYPE_STRING;
2764  s->opt[OPT_SECTION].unit = SANE_UNIT_NONE;
2765  s->opt[OPT_SECTION].constraint_type = SANE_CONSTRAINT_NONE;
2766  s->opt[OPT_SECTION].size = 255;
2767  s->val[OPT_SECTION].s = strdup ("");
2768
2769  /* Barcode_Relmax */
2770  s->opt[OPT_BARCODE_RELMAX].name = SANE_NAME_BARCODE_RELMAX;
2771  s->opt[OPT_BARCODE_RELMAX].title = SANE_TITLE_BARCODE_RELMAX;
2772  s->opt[OPT_BARCODE_RELMAX].desc = SANE_DESC_BARCODE_RELMAX;
2773  s->opt[OPT_BARCODE_RELMAX].type = SANE_TYPE_INT;
2774  s->opt[OPT_BARCODE_RELMAX].unit = SANE_UNIT_NONE;
2775  s->opt[OPT_BARCODE_RELMAX].constraint_type = SANE_CONSTRAINT_RANGE;
2776  s->opt[OPT_BARCODE_RELMAX].constraint.range = &u8_range;
2777  s->val[OPT_BARCODE_RELMAX].w = 0;
2778
2779  /* Barcode_Barmin */
2780  s->opt[OPT_BARCODE_BARMIN].name = SANE_NAME_BARCODE_BARMIN;
2781  s->opt[OPT_BARCODE_BARMIN].title = SANE_TITLE_BARCODE_BARMIN;
2782  s->opt[OPT_BARCODE_BARMIN].desc = SANE_DESC_BARCODE_BARMIN;
2783  s->opt[OPT_BARCODE_BARMIN].type = SANE_TYPE_INT;
2784  s->opt[OPT_BARCODE_BARMIN].unit = SANE_UNIT_NONE;
2785  s->opt[OPT_BARCODE_BARMIN].constraint_type = SANE_CONSTRAINT_RANGE;
2786  s->opt[OPT_BARCODE_BARMIN].constraint.range = &u8_range;
2787  s->val[OPT_BARCODE_BARMIN].w = 0;
2788
2789  /* Barcode_Barmax */
2790  s->opt[OPT_BARCODE_BARMAX].name = SANE_NAME_BARCODE_BARMAX;
2791  s->opt[OPT_BARCODE_BARMAX].title = SANE_TITLE_BARCODE_BARMAX;
2792  s->opt[OPT_BARCODE_BARMAX].desc = SANE_DESC_BARCODE_BARMAX;
2793  s->opt[OPT_BARCODE_BARMAX].type = SANE_TYPE_INT;
2794  s->opt[OPT_BARCODE_BARMAX].unit = SANE_UNIT_NONE;
2795  s->opt[OPT_BARCODE_BARMAX].constraint_type = SANE_CONSTRAINT_RANGE;
2796  s->opt[OPT_BARCODE_BARMAX].constraint.range = &u8_range;
2797  s->val[OPT_BARCODE_BARMAX].w = 0;
2798
2799  /* Barcode_Contrast */
2800  s->opt[OPT_BARCODE_CONTRAST].name = SANE_NAME_BARCODE_CONTRAST;
2801  s->opt[OPT_BARCODE_CONTRAST].title = SANE_TITLE_BARCODE_CONTRAST;
2802  s->opt[OPT_BARCODE_CONTRAST].desc = SANE_DESC_BARCODE_CONTRAST;
2803  s->opt[OPT_BARCODE_CONTRAST].type = SANE_TYPE_INT;
2804  s->opt[OPT_BARCODE_CONTRAST].unit = SANE_UNIT_NONE;
2805  s->opt[OPT_BARCODE_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
2806  s->opt[OPT_BARCODE_CONTRAST].constraint.range = &barcode_contrast_range;
2807  s->val[OPT_BARCODE_CONTRAST].w = 3;
2808
2809  /* Barcode_Patchmode */
2810  s->opt[OPT_BARCODE_PATCHMODE].name = SANE_NAME_BARCODE_PATCHMODE;
2811  s->opt[OPT_BARCODE_PATCHMODE].title = SANE_TITLE_BARCODE_PATCHMODE;
2812  s->opt[OPT_BARCODE_PATCHMODE].desc = SANE_DESC_BARCODE_PATCHMODE;
2813  s->opt[OPT_BARCODE_PATCHMODE].type = SANE_TYPE_INT;
2814  s->opt[OPT_BARCODE_PATCHMODE].unit = SANE_UNIT_NONE;
2815  s->opt[OPT_BARCODE_PATCHMODE].constraint_type = SANE_CONSTRAINT_RANGE;
2816  s->opt[OPT_BARCODE_PATCHMODE].constraint.range = &barcode_patchmode_range;
2817  s->val[OPT_BARCODE_PATCHMODE].w = 0;
2818
2819  if (s->hw->info.canSection == SANE_FALSE)
2820    {
2821      s->opt[OPT_SECTION].cap |= SANE_CAP_INACTIVE;
2822    }
2823
2824  if (s->hw->info.canBarCode == SANE_FALSE)
2825    {
2826      s->opt[OPT_BARCODE_GROUP].cap |= SANE_CAP_INACTIVE;
2827      s->opt[OPT_BARCODE_SEARCH_BAR].cap |= SANE_CAP_INACTIVE;
2828      s->opt[OPT_BARCODE_SEARCH_COUNT].cap |= SANE_CAP_INACTIVE;
2829      s->opt[OPT_BARCODE_SEARCH_MODE].cap |= SANE_CAP_INACTIVE;
2830      s->opt[OPT_BARCODE_HMIN].cap |= SANE_CAP_INACTIVE;
2831      s->opt[OPT_BARCODE_SEARCH_TIMEOUT].cap |= SANE_CAP_INACTIVE;
2832      s->opt[OPT_BARCODE_RELMAX].cap |= SANE_CAP_INACTIVE;
2833      s->opt[OPT_BARCODE_BARMIN].cap |= SANE_CAP_INACTIVE;
2834      s->opt[OPT_BARCODE_BARMAX].cap |= SANE_CAP_INACTIVE;
2835      s->opt[OPT_BARCODE_CONTRAST].cap |= SANE_CAP_INACTIVE;
2836      s->opt[OPT_BARCODE_PATCHMODE].cap |= SANE_CAP_INACTIVE;
2837    }
2838
2839  return SANE_STATUS_GOOD;
2840}
2841
2842static SANE_Status
2843attach (const char *devnam, BH_Device ** devp)
2844{
2845  SANE_Status status;
2846  BH_Device *dev;
2847  struct inquiry_standard_data ibuf;
2848  struct inquiry_vpd_data vbuf;
2849  struct inquiry_jis_data jbuf;
2850  size_t buf_size;
2851  int fd = -1;
2852  double mm;
2853
2854  DBG (3, "attach called\n");
2855
2856  for (dev = first_dev; dev; dev = dev->next)
2857    {
2858      if (strcmp (dev->sane.name, devnam) == 0)
2859        {
2860          if (devp)
2861            *devp = dev;
2862          return SANE_STATUS_GOOD;
2863        }
2864    }
2865
2866#ifdef FAKE_INQUIRY
2867  if (fake_inquiry)
2868    {
2869      DBG (3, "attach: faking inquiry of %s\n", devnam);
2870
2871      memset (&ibuf, 0, sizeof (ibuf));
2872      ibuf.devtype = 6;
2873      memcpy(ibuf.vendor, "**FAKE**", 8);
2874      memcpy(ibuf.product, "COPISCAN II 6338", 16);
2875      memcpy(ibuf.revision, "0016", 4);
2876
2877      DBG (1, "attach: reported devtype='%d', vendor='%.8s', "
2878	   "product='%.16s', revision='%.4s'\n",
2879	   ibuf.devtype, ibuf.vendor,
2880	   ibuf.product, ibuf.revision);
2881
2882      memset (&vbuf, 0, sizeof (vbuf));
2883      memset (&jbuf, 0, sizeof (jbuf));
2884    }
2885  else
2886#endif
2887    {
2888      DBG (3, "attach: opening %s\n", devnam);
2889      status = sanei_scsi_open (devnam, &fd, sense_handler, NULL);
2890      if (status != SANE_STATUS_GOOD)
2891	{
2892	  DBG (1, "attach: open failed: %s\n", sane_strstatus (status));
2893	  return status;
2894	}
2895
2896      DBG (3, "attach: sending TEST_UNIT_READY\n");
2897      status = test_unit_ready (fd);
2898      if (status != SANE_STATUS_GOOD)
2899	{
2900	  DBG (1, "attach: test unit ready failed (%s)\n",
2901	       sane_strstatus (status));
2902	  sanei_scsi_close (fd);
2903	  return status;
2904	}
2905
2906      DBG (3, "attach: sending INQUIRY (standard data)\n");
2907      memset (&ibuf, 0, sizeof (ibuf));
2908      buf_size = sizeof(ibuf);
2909      status = inquiry (fd, &ibuf, &buf_size, 0,
2910			BH_INQUIRY_STANDARD_PAGE_CODE);
2911      if (status != SANE_STATUS_GOOD)
2912	{
2913	  DBG (1, "attach: inquiry (standard data) failed: %s\n",
2914	       sane_strstatus (status));
2915	  sanei_scsi_close (fd);
2916	  return status;
2917	}
2918
2919      DBG (1, "attach: reported devtype='%d', vendor='%.8s', "
2920	   "product='%.16s', revision='%.4s'\n",
2921	   ibuf.devtype, ibuf.vendor,
2922	   ibuf.product, ibuf.revision);
2923
2924      if (ibuf.devtype != 6
2925	  || strncmp ((char *)ibuf.vendor, "B&H SCSI", 8) != 0
2926	  || strncmp ((char *)ibuf.product, "COPISCAN ", 9) != 0)
2927	{
2928	  DBG (1,
2929	       "attach: device is not a recognized Bell and Howell scanner\n");
2930	  sanei_scsi_close (fd);
2931	  return SANE_STATUS_INVAL;
2932	}
2933
2934      DBG (3, "attach: sending INQUIRY (vpd data)\n");
2935      memset (&vbuf, 0, sizeof (vbuf));
2936      buf_size = sizeof(vbuf);
2937      status = inquiry (fd, &vbuf, &buf_size, 1,
2938			BH_INQUIRY_VPD_PAGE_CODE);
2939      if (status != SANE_STATUS_GOOD)
2940	{
2941	  DBG (1, "attach: inquiry (vpd data) failed: %s\n",
2942	       sane_strstatus (status));
2943	  sanei_scsi_close (fd);
2944	  return status;
2945	}
2946
2947      DBG (3, "attach: sending INQUIRY (jis data)\n");
2948      memset (&jbuf, 0, sizeof (jbuf));
2949      buf_size = sizeof(jbuf);
2950      status = inquiry (fd, &jbuf, &buf_size, 1,
2951			BH_INQUIRY_JIS_PAGE_CODE);
2952      if (status != SANE_STATUS_GOOD)
2953	{
2954	  DBG (1, "attach: inquiry (jis data) failed: %s\n",
2955	       sane_strstatus (status));
2956	  sanei_scsi_close (fd);
2957	  return status;
2958	}
2959
2960      sanei_scsi_close (fd);
2961    }
2962
2963  dev = malloc (sizeof (*dev));
2964  if (!dev)
2965    return SANE_STATUS_NO_MEM;
2966  memset (dev, 0, sizeof (*dev));
2967
2968
2969  dev->info.devtype = ibuf.devtype;
2970  sprintf(dev->info.vendor, "%.8s", ibuf.vendor);
2971  trim_spaces(dev->info.vendor, sizeof(dev->info.vendor));
2972  sprintf(dev->info.product, "%.16s", ibuf.product);
2973  trim_spaces(dev->info.product, sizeof(dev->info.product));
2974  sprintf(dev->info.revision, "%.4s", ibuf.revision);
2975  trim_spaces(dev->info.revision, sizeof(dev->info.revision));
2976
2977  dev->sane.name = strdup (devnam);
2978  dev->sane.vendor = strdup(dev->info.vendor);
2979  dev->sane.model = strdup(dev->info.product);;
2980  dev->sane.type = strdup(print_devtype(dev->info.devtype));
2981
2982  /* set capabilities from vpd */
2983  dev->info.canADF = vbuf.adf & 0x01;
2984  dev->info.colorBandW = vbuf.imagecomposition & 0x01;
2985  dev->info.colorHalftone = vbuf.imagecomposition & 0x02;
2986  dev->info.canWhiteFrame = vbuf.imagedataprocessing[1] & 0x01;
2987  dev->info.canBlackFrame = vbuf.imagedataprocessing[1] & 0x02;
2988  dev->info.canEdgeExtract = vbuf.imagedataprocessing[1] & 0x04;
2989  dev->info.canNoiseFilter = vbuf.imagedataprocessing[1] & 0x08;
2990  dev->info.canSmooth = vbuf.imagedataprocessing[1] & 0x10;
2991  dev->info.canLineBold = vbuf.imagedataprocessing[1] & 0x20;
2992  dev->info.comprG3_1D = vbuf.compression & 0x01;
2993  dev->info.comprG3_2D = vbuf.compression & 0x02;
2994  dev->info.comprG4 = vbuf.compression & 0x04;
2995  dev->info.canBorderRecog = vbuf.sizerecognition & 0x01;
2996  dev->info.canBarCode = vbuf.optionalfeatures & 0x01;
2997  dev->info.canIcon = vbuf.optionalfeatures & 0x02;
2998  dev->info.canSection = vbuf.optionalfeatures & 0x04;
2999  dev->info.lineMaxBytes = _2btol(vbuf.xmaxoutputbytes);
3000
3001#ifdef FAKE_INQUIRY
3002  if (fake_inquiry)
3003    {
3004      dev->info.canADF = SANE_FALSE;
3005      dev->info.colorBandW = SANE_TRUE;
3006      dev->info.colorHalftone = SANE_TRUE;
3007      dev->info.canWhiteFrame = SANE_TRUE;
3008      dev->info.canBlackFrame = SANE_TRUE;
3009      dev->info.canEdgeExtract = SANE_TRUE;
3010      dev->info.canNoiseFilter = SANE_TRUE;
3011      dev->info.canSmooth = SANE_TRUE;
3012      dev->info.canLineBold = SANE_TRUE;
3013      dev->info.comprG3_1D = SANE_TRUE;
3014      dev->info.comprG3_2D = SANE_TRUE;
3015      dev->info.comprG4 = SANE_TRUE;
3016      dev->info.canBorderRecog = SANE_TRUE;
3017      dev->info.canBarCode = SANE_TRUE;
3018      dev->info.canIcon = SANE_TRUE;
3019      dev->info.canSection = SANE_TRUE;
3020      dev->info.lineMaxBytes = 450;
3021    }
3022#endif
3023
3024  /* set capabilities from jis */
3025  dev->info.resBasicX = _2btol(jbuf.basicxres);
3026  dev->info.resBasicY = _2btol(jbuf.basicyres);
3027  dev->info.resMaxX = _2btol(jbuf.maxxres);
3028  dev->info.resMaxY = _2btol(jbuf.maxyres);
3029  dev->info.resMinX = _2btol(jbuf.minxres);
3030  dev->info.resMinY = _2btol(jbuf.minyres);
3031
3032  /* set the length of the list to zero first, then append standard resolutions */
3033  dev->info.resStdList[0] = 0;
3034  if (jbuf.standardres[0] & 0x80) appendStdList(&dev->info, 60);
3035  if (jbuf.standardres[0] & 0x40) appendStdList(&dev->info, 75);
3036  if (jbuf.standardres[0] & 0x20) appendStdList(&dev->info, 100);
3037  if (jbuf.standardres[0] & 0x10) appendStdList(&dev->info, 120);
3038  if (jbuf.standardres[0] & 0x08) appendStdList(&dev->info, 150);
3039  if (jbuf.standardres[0] & 0x04) appendStdList(&dev->info, 160);
3040  if (jbuf.standardres[0] & 0x02) appendStdList(&dev->info, 180);
3041  if (jbuf.standardres[0] & 0x01) appendStdList(&dev->info, 200);
3042  if (jbuf.standardres[1] & 0x80) appendStdList(&dev->info, 240);
3043  if (jbuf.standardres[1] & 0x40) appendStdList(&dev->info, 300);
3044  if (jbuf.standardres[1] & 0x20) appendStdList(&dev->info, 320);
3045  if (jbuf.standardres[1] & 0x10) appendStdList(&dev->info, 400);
3046  if (jbuf.standardres[1] & 0x08) appendStdList(&dev->info, 480);
3047  if (jbuf.standardres[1] & 0x04) appendStdList(&dev->info, 600);
3048  if (jbuf.standardres[1] & 0x02) appendStdList(&dev->info, 800);
3049  if (jbuf.standardres[1] & 0x01) appendStdList(&dev->info, 1200);
3050  if (dev->info.resStdList[0] == 0)
3051    {
3052      /* make a default standard resolutions for 200 and 300dpi */
3053      DBG(1, "attach: no standard resolutions reported\n");
3054      dev->info.resStdList[0] = 2;
3055      dev->info.resStdList[1] = 200;
3056      dev->info.resStdList[2] = 300;
3057      dev->info.resBasicX = dev->info.resBasicY = 300;
3058    }
3059
3060  dev->info.winWidth = _4btol(jbuf.windowwidth);
3061  dev->info.winHeight = _4btol(jbuf.windowlength);
3062
3063  if (dev->info.winWidth <= 0)
3064    {
3065      dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5);
3066      DBG(1, "attach: invalid window width reported, using %d\n", dev->info.winWidth);
3067    }
3068  if (dev->info.winHeight <= 0)
3069    {
3070      dev->info.winHeight = dev->info.resBasicY * 14;
3071      DBG(1, "attach: invalid window height reported, using %d\n", dev->info.winHeight);
3072    }
3073
3074  mm = (dev->info.resBasicX > 0) ?
3075    ((double) dev->info.winWidth / (double) dev->info.resBasicX * MM_PER_INCH) :
3076    0.0;
3077  dev->info.x_range.min = SANE_FIX(0.0);
3078  dev->info.x_range.max = SANE_FIX(mm);
3079  dev->info.x_range.quant = SANE_FIX(0.0);
3080
3081  mm = (dev->info.resBasicY > 0) ?
3082    ((double) dev->info.winHeight / (double) dev->info.resBasicY * MM_PER_INCH) :
3083    0.0;
3084  dev->info.y_range.min = SANE_FIX(0.0);
3085  dev->info.y_range.max = SANE_FIX(mm);
3086  dev->info.y_range.quant = SANE_FIX(0.0);
3087
3088  /* set additional discovered/guessed capabilities */
3089
3090  /* if all of the ACE capabilities are present, declare it ACE capable */
3091  dev->info.canACE = dev->info.canEdgeExtract &&
3092    dev->info.canNoiseFilter &&
3093    dev->info.canSmooth &&
3094    dev->info.canLineBold;
3095
3096  /* if the model is known to be a duplex, declare it duplex capable */
3097  if (strcmp(dev->info.product, "COPISCAN II 6338") == 0)
3098    {
3099      dev->info.canDuplex = SANE_TRUE;
3100    }
3101  else
3102    {
3103      dev->info.canDuplex = SANE_FALSE;
3104    }
3105
3106  /* the paper sensor requires RSC revision 1.4 or higher and an
3107   * installed feeder.  NOTE: It also requires SW-4 on and the
3108   * AccufeedPlus feeder, but we cannot discover that.
3109   */
3110  if (strcmp(dev->info.revision, "0014") >= 0)
3111    {
3112      dev->info.canCheckADF = dev->info.canADF;
3113    }
3114  else
3115    {
3116      dev->info.canCheckADF = SANE_FALSE;
3117    }
3118
3119  /* set option defaults based on inquiry information */
3120  dev->info.res_default = dev->info.resBasicX;
3121  dev->info.autoborder_default = dev->info.canBorderRecog;
3122  dev->info.batch_default = SANE_FALSE;
3123  dev->info.deskew_default = SANE_FALSE;
3124  dev->info.check_adf_default = SANE_FALSE;
3125  dev->info.duplex_default = SANE_FALSE;
3126  dev->info.timeout_adf_default = 0;
3127  dev->info.timeout_manual_default = 0;
3128  dev->info.control_panel_default = dev->info.canACE;
3129
3130  ++num_devices;
3131  dev->next = first_dev;
3132  first_dev = dev;
3133
3134  if (devp)
3135    *devp = dev;
3136
3137  return SANE_STATUS_GOOD;
3138}
3139
3140static SANE_Status
3141attach_one(const char *devnam)
3142{
3143  attach (devnam, NULL);
3144  return SANE_STATUS_GOOD;
3145}
3146
3147SANE_Status
3148sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize)
3149{
3150    char devnam[PATH_MAX] = "/dev/scanner";
3151    FILE *fp;
3152
3153    (void) authorize; /* get rid of compiler warning */
3154
3155    DBG_INIT();
3156    DBG(3, "sane_init called\n");
3157    DBG(1, "Bell+Howell SANE backend %d.%d build %d %s endian\n",
3158	SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD,
3159	_is_host_little_endian() ? "little" : "big");
3160
3161    if (version_code)
3162	*version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD);
3163
3164    fp = sanei_config_open(BH_CONFIG_FILE);
3165    if (fp)
3166	{
3167	    char line[PATH_MAX];
3168	    const char *lp;
3169	    size_t len;
3170
3171	    /* read config file */
3172	    while (sanei_config_read (line, sizeof (line), fp))
3173		{
3174		  if (line[0] == '#')           /* ignore line comments */
3175		    continue;
3176		  len = strlen (line);
3177
3178		  if (!len)
3179		    continue;                   /* ignore empty lines */
3180
3181		  lp = sanei_config_skip_whitespace (line);
3182
3183		  DBG(16,
3184		      "sane_init: processing config file line '%s'\n",
3185		      line);
3186		  if (strncmp(lp, "option", 6) == 0 &&
3187		      (isspace (lp[6]) || lp[6] == '\0'))
3188		    {
3189		      lp += 6;
3190		      lp = sanei_config_skip_whitespace (lp);
3191
3192		      if (strncmp(lp, "disable-optional-frames", 23) == 0)
3193			{
3194			  DBG(1, "sane_init: configuration option "
3195			      "'disable-optional-frames' set\n");
3196			  disable_optional_frames = 1;
3197			}
3198		      else if (strncmp(lp, "fake-inquiry", 12) == 0)
3199			{
3200			  DBG(1, "sane_init: configuration option "
3201			      "'fake-inquiry' set\n");
3202			  fake_inquiry = 1;
3203			}
3204		      else
3205			{
3206			  DBG(1, "sane_init: ignoring unknown "
3207			      "configuration option '%s'\n",
3208			      lp);
3209			}
3210		    }
3211		  else
3212		    {
3213		      DBG(16,
3214			  "sane_init: found a device: line '%s'\n",
3215			  lp);
3216		      strncpy (devnam, lp, sizeof(devnam));
3217		      devnam[sizeof(devnam)-1] = '\0';
3218
3219		      sanei_config_attach_matching_devices(devnam,
3220							   attach_one);
3221		    }
3222		}
3223	    fclose (fp);
3224	}
3225    else
3226	{
3227	    /* configure the /dev/scanner device in the absence of config file */
3228	    sanei_config_attach_matching_devices ("/dev/scanner", attach_one);
3229	}
3230
3231    return SANE_STATUS_GOOD;
3232}
3233
3234SANE_Status
3235sane_get_devices (const SANE_Device ***device_list, SANE_Bool local)
3236{
3237    BH_Device *dev;
3238    int i;
3239    DBG(3, "sane_get_devices called\n");
3240
3241    (void) local; /* get rid of compiler warning */
3242    if (devlist)
3243	free (devlist);
3244    devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
3245    if (!devlist)
3246	return SANE_STATUS_NO_MEM;
3247
3248    i = 0;
3249    for (dev = first_dev; dev; dev = dev->next)
3250	devlist[i++] = &dev->sane;
3251    devlist[i++] = 0;
3252
3253    *device_list = devlist;
3254
3255    return SANE_STATUS_GOOD;
3256}
3257
3258SANE_Status
3259sane_open (SANE_String_Const devnam, SANE_Handle *handle)
3260{
3261    SANE_Status status;
3262    BH_Device *dev;
3263    BH_Scanner *s;
3264    DBG(3, "sane_open called\n");
3265
3266    if (devnam[0] != '\0')
3267	{
3268	    for (dev = first_dev; dev; dev = dev->next)
3269		{
3270		    if (strcmp (dev->sane.name, devnam) == 0)
3271		      break;
3272		}
3273
3274	    if (!dev)
3275		{
3276		    status = attach (devnam, &dev);
3277		    if (status != SANE_STATUS_GOOD)
3278			return status;
3279		}
3280	}
3281    else
3282	{
3283	    dev = first_dev;
3284	}
3285
3286    if (!dev)
3287	return SANE_STATUS_INVAL;
3288
3289    s = malloc (sizeof (*s));
3290    if (!s)
3291	return SANE_STATUS_NO_MEM;
3292    memset (s, 0, sizeof (*s));
3293
3294    s->fd = -1;
3295    s->hw = dev;
3296
3297    s->bmu = BH_UNIT_POINT;
3298    s->mud = 1;
3299
3300    ScannerDump(s);
3301
3302    init_options (s);
3303
3304    s->next = first_handle;
3305    first_handle = s;
3306
3307    /* initialize our parameters */
3308    get_parameters(s, 0);
3309
3310    *handle = s;
3311
3312#ifdef FAKE_INQUIRY
3313    if (fake_inquiry)
3314      {
3315	DBG (1, "sane_open: faking open of %s\n",
3316	     s->hw->sane.name);
3317      }
3318    else
3319#endif
3320      {
3321	status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s);
3322	if (status != SANE_STATUS_GOOD)
3323	  {
3324	    DBG (1, "sane_open: open of %s failed: %s\n",
3325		 s->hw->sane.name, sane_strstatus (status));
3326	    return status;
3327	  }
3328      }
3329
3330    return SANE_STATUS_GOOD;
3331}
3332
3333const SANE_Option_Descriptor *
3334sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
3335{
3336  BH_Scanner *s = handle;
3337  DBG(3, "sane_get_option_descriptor called (option:%d)\n", option);
3338
3339  if ((unsigned) option >= NUM_OPTIONS)
3340      return 0;
3341
3342  return (s->opt + option);
3343}
3344
3345SANE_Status
3346sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action,
3347		     void *val, SANE_Word *info)
3348{
3349  BH_Scanner *s = handle;
3350  SANE_Status status;
3351  SANE_Word cap;
3352  SANE_String_Const name;
3353
3354  DBG(3, "sane_control_option called\n");
3355
3356  name = s->opt[option].name ? s->opt[option].name : "(nil)";
3357
3358  if (info)
3359    *info = 0;
3360
3361  if (s->scanning && action == SANE_ACTION_SET_VALUE)
3362    return SANE_STATUS_DEVICE_BUSY;
3363  if (option >= NUM_OPTIONS)
3364    return SANE_STATUS_INVAL;
3365
3366  cap = s->opt[option].cap;
3367  if (!SANE_OPTION_IS_ACTIVE (cap))
3368    return SANE_STATUS_INVAL;
3369
3370  if (action == SANE_ACTION_GET_VALUE)
3371    {
3372      DBG(16, "sane_control_option: get_value %s [#%d]\n", name, option);
3373      switch (option)
3374	{
3375	  /* word options: */
3376	case OPT_RESOLUTION:
3377	case OPT_TL_X:
3378	case OPT_TL_Y:
3379	case OPT_BR_X:
3380	case OPT_BR_Y:
3381	case OPT_TIMEOUT_ADF:
3382	case OPT_TIMEOUT_MANUAL:
3383	case OPT_ACE_FUNCTION:
3384	case OPT_ACE_SENSITIVITY:
3385	case OPT_BRIGHTNESS:
3386	case OPT_THRESHOLD:
3387	case OPT_CONTRAST:
3388	case OPT_ICON_WIDTH:
3389	case OPT_ICON_LENGTH:
3390	case OPT_BARCODE_SEARCH_COUNT:
3391	case OPT_BARCODE_HMIN:
3392	case OPT_BARCODE_SEARCH_TIMEOUT:
3393	case OPT_BARCODE_RELMAX:
3394	case OPT_BARCODE_BARMIN:
3395	case OPT_BARCODE_BARMAX:
3396	case OPT_BARCODE_CONTRAST:
3397	case OPT_BARCODE_PATCHMODE:
3398	case OPT_NUM_OPTS:
3399	  *(SANE_Word *) val = s->val[option].w;
3400	  return SANE_STATUS_GOOD;
3401
3402	  /* string options: */
3403	case OPT_INQUIRY:
3404	case OPT_SCAN_SOURCE:
3405	case OPT_SCAN_MODE:
3406	case OPT_COMPRESSION:
3407	case OPT_PAPER_SIZE:
3408	case OPT_ROTATION:
3409	case OPT_BARCODE_SEARCH_BAR:
3410	case OPT_BARCODE_SEARCH_MODE:
3411	case OPT_SECTION:
3412	  strcpy (val, s->val[option].s);
3413	  return SANE_STATUS_GOOD;
3414
3415	  /* boolean options: */
3416	case OPT_PREVIEW:
3417	case OPT_AUTOBORDER:
3418	case OPT_DESKEW:
3419	case OPT_BATCH:
3420	case OPT_CHECK_ADF:
3421	case OPT_DUPLEX:
3422	case OPT_CONTROL_PANEL:
3423	case OPT_NEGATIVE:
3424	  *(SANE_Word *) val = s->val[option].w;
3425	  return SANE_STATUS_GOOD;
3426
3427	default:
3428	  DBG(1, "sane_control_option:invalid option number %d\n", option);
3429	  return SANE_STATUS_INVAL;
3430	}
3431    }
3432  else if (action == SANE_ACTION_SET_VALUE)
3433    {
3434      switch (s->opt[option].type)
3435	{
3436	case SANE_TYPE_BOOL:
3437	case SANE_TYPE_INT:
3438	  DBG(16, "sane_control_option: set_value %s [#%d] to %d\n",
3439	      name, option, *(SANE_Word *) val);
3440	  break;
3441
3442	case SANE_TYPE_FIXED:
3443	  DBG(16, "sane_control_option: set_value %s [#%d] to %f\n",
3444	      name, option, SANE_UNFIX(*(SANE_Word *) val));
3445	  break;
3446
3447	case SANE_TYPE_STRING:
3448	  DBG(16, "sane_control_option: set_value %s [#%d] to %s\n",
3449	      name, option, (char *) val);
3450	  break;
3451
3452	default:
3453	  DBG(16, "sane_control_option: set_value %s [#%d]\n",
3454	      name, option);
3455	}
3456
3457      if (!SANE_OPTION_IS_SETTABLE (cap))
3458	return SANE_STATUS_INVAL;
3459
3460      status = sanei_constrain_value (s->opt + option, val, info);
3461      if (status != SANE_STATUS_GOOD)
3462	return status;
3463
3464      switch (option)
3465	{
3466	  /* (mostly) side-effect-free word options: */
3467	case OPT_TL_X:
3468	case OPT_TL_Y:
3469	case OPT_BR_X:
3470	case OPT_BR_Y:
3471	  /* make sure that paper-size is set to custom */
3472	  if (s->val[option].w != *(SANE_Word *) val)
3473	    {
3474	      if (info) *info |= SANE_INFO_RELOAD_PARAMS;
3475
3476	      if (get_paper_id(_OPT_VAL_STRING(s, OPT_PAPER_SIZE)) != 0)
3477		{
3478		  if (info) *info |= SANE_INFO_RELOAD_OPTIONS;
3479
3480		  /* set paper size to 'custom' */
3481		  free (s->val[OPT_PAPER_SIZE].s);
3482		  s->val[OPT_PAPER_SIZE].s = strdup(paper_list[0]);
3483		}
3484	    }
3485	  /* fall through */
3486	case OPT_RESOLUTION:
3487	  if (info && s->val[option].w != *(SANE_Word *) val)
3488	    *info |= SANE_INFO_RELOAD_PARAMS;
3489	  /* fall through */
3490	case OPT_TIMEOUT_ADF:
3491	case OPT_TIMEOUT_MANUAL:
3492	case OPT_ACE_FUNCTION:
3493	case OPT_ACE_SENSITIVITY:
3494	case OPT_BRIGHTNESS:
3495	case OPT_THRESHOLD:
3496	case OPT_CONTRAST:
3497	case OPT_ICON_WIDTH:
3498	case OPT_ICON_LENGTH:
3499	case OPT_BARCODE_SEARCH_COUNT:
3500	case OPT_BARCODE_HMIN:
3501	case OPT_BARCODE_SEARCH_TIMEOUT:
3502	case OPT_BARCODE_RELMAX:
3503	case OPT_BARCODE_BARMIN:
3504	case OPT_BARCODE_BARMAX:
3505	case OPT_BARCODE_CONTRAST:
3506	case OPT_BARCODE_PATCHMODE:
3507	case OPT_NUM_OPTS:
3508	  s->val[option].w = *(SANE_Word *) val;
3509	  return SANE_STATUS_GOOD;
3510
3511	  /* string options */
3512	case OPT_BARCODE_SEARCH_BAR:
3513	  /*!!! we're supporting only a single barcode type via the option */
3514	  s->search_bars[0] = get_barcode_id(val);
3515	  /* fall through */
3516	case OPT_SCAN_SOURCE:
3517	case OPT_COMPRESSION:
3518	case OPT_ROTATION:
3519	case OPT_BARCODE_SEARCH_MODE:
3520	case OPT_SECTION:
3521	  if (s->val[option].s)
3522	    free (s->val[option].s);
3523	  s->val[option].s = strdup (val);
3524	  return SANE_STATUS_GOOD;
3525
3526	  /* boolean options: */
3527	case OPT_AUTOBORDER:
3528	  /*!!! autoborder true disables geometry controls
3529	   * and sets them to defaults?
3530	   */
3531	  /* fall through */
3532	case OPT_PREVIEW:
3533	case OPT_BATCH:
3534	case OPT_DESKEW:
3535	case OPT_CHECK_ADF:
3536	case OPT_DUPLEX:
3537	case OPT_NEGATIVE:
3538	  s->val[option].w = *(SANE_Word *) val;
3539	  return SANE_STATUS_GOOD;
3540
3541	  /* options with side effects */
3542	case OPT_CONTROL_PANEL:
3543	  /* a boolean option */
3544	  /* control-panel true enables/disables some enhancement controls */
3545	  if (s->val[option].w != *(SANE_Word *) val)
3546	    {
3547	      if (info) *info |= SANE_INFO_RELOAD_OPTIONS;
3548
3549	      s->val[option].w = *(SANE_Word *) val;
3550
3551	      if (*(SANE_Word *) val == SANE_TRUE)
3552		{
3553		  if (s->hw->info.canACE == SANE_TRUE)
3554		    {
3555		      s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE;
3556		      s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE;
3557		    }
3558		  else
3559		    {
3560		      s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
3561		      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
3562		    }
3563		}
3564	      else
3565		{
3566		  if (s->hw->info.canACE == SANE_TRUE)
3567		    {
3568		      s->opt[OPT_ACE_FUNCTION].cap &= ~SANE_CAP_INACTIVE;
3569		      s->opt[OPT_ACE_SENSITIVITY].cap &= ~SANE_CAP_INACTIVE;
3570		    }
3571		  else
3572		    {
3573		      s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
3574		      s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
3575		    }
3576		}
3577	    }
3578	  return SANE_STATUS_GOOD;
3579
3580	case OPT_SCAN_MODE:
3581	  /* a string option */
3582	  /* scan mode != lineart disables compression, setting it to
3583	   * 'none'
3584	   */
3585	  if (strcmp (s->val[option].s, (SANE_String) val))
3586	    {
3587	      if (info) *info |= SANE_INFO_RELOAD_OPTIONS;
3588	      if (get_scan_mode_id((SANE_String) val) != 0)
3589		{
3590		  /* scan mode is not lineart, disable compression
3591		   * and set compression to 'none'
3592		   */
3593		  s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE;
3594		  if (s->val[OPT_COMPRESSION].s &&
3595		      get_compression_id(s->val[OPT_COMPRESSION].s) != 0)
3596		    {
3597		      free (s->val[OPT_COMPRESSION].s);
3598		      s->val[OPT_COMPRESSION].s = strdup(compression_list[0]);
3599		    }
3600		}
3601	      else
3602		{
3603		  /* scan mode is lineart, enable compression */
3604		  s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE;
3605		}
3606	      free (s->val[option].s);
3607	      s->val[option].s = strdup (val);
3608	    }
3609	  return SANE_STATUS_GOOD;
3610
3611	case OPT_PAPER_SIZE:
3612	  /* a string option */
3613	  /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */
3614	  if (strcmp (s->val[option].s, (SANE_String) val))
3615	    {
3616	      SANE_Int paper_id = get_paper_id((SANE_String) val);
3617
3618	      /* paper_id 0 is a special case (custom) that
3619	       * disables the paper size control of geometry
3620	       */
3621	      if (paper_id != 0)
3622		{
3623		  double left, x_max, y_max, x, y;
3624
3625		  x_max = SANE_UNFIX(s->hw->info.x_range.max);
3626		  y_max = SANE_UNFIX(s->hw->info.y_range.max);
3627		  /* a dimension of 0.0 (or less) is replaced with the max value */
3628		  x = (paper_sizes[paper_id].width <= 0.0) ? x_max :
3629		    paper_sizes[paper_id].width;
3630		  y = (paper_sizes[paper_id].length <= 0.0) ? y_max :
3631		    paper_sizes[paper_id].length;
3632
3633		  if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
3634
3635		  /* set geometry options based on paper size */
3636		  /* set geometry options based on paper size */
3637		  if (s->hw->info.canADF)
3638		    {
3639		      /* when the feeder is used the paper is centered in the
3640		       * hopper; with the manual feed it is aligned left.
3641		       */
3642		      left = (x_max - x) / 2.0;
3643		      if (left < 0.0) left = 0.0;
3644		    }
3645		  else
3646		    {
3647		      left = 0.0;
3648		    }
3649
3650		  s->val[OPT_TL_X].w = SANE_FIX(left);
3651		  s->val[OPT_TL_Y].w = SANE_FIX(0.0);
3652		  s->val[OPT_BR_X].w = SANE_FIX(MIN(x + left, x_max));
3653		  s->val[OPT_BR_Y].w = SANE_FIX(MIN(y, y_max));
3654		}
3655	      free (s->val[option].s);
3656	      s->val[option].s = strdup (val);
3657	    }
3658	  return SANE_STATUS_GOOD;
3659
3660	default:
3661	  DBG(1, "sane_control_option:invalid option number %d\n", option);
3662	  return SANE_STATUS_INVAL;
3663	}
3664    }
3665
3666  return SANE_STATUS_INVAL;
3667}
3668
3669SANE_Status
3670sane_get_parameters (SANE_Handle handle, SANE_Parameters *params)
3671{
3672  BH_Scanner *s = handle;
3673  SANE_Int status = SANE_STATUS_GOOD;
3674
3675  DBG(3, "sane_get_parameters called\n");
3676
3677  if (params)
3678    {
3679      SANE_Int res;
3680
3681      if (!s->scanning)
3682	{
3683	  /* update our parameters ONLY if we're not scanning */
3684	  status = get_parameters(s, 0);
3685	}
3686
3687      *params = s->params;
3688
3689      res = _OPT_VAL_WORD(s, OPT_RESOLUTION);
3690
3691      DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, "
3692	   "lines=%d, dpi=%d\n",
3693	   (int) s->params.format,
3694	   s->params.pixels_per_line,
3695	   s->params.bytes_per_line,
3696	   s->params.lines,
3697	   res);
3698    }
3699
3700  return status;
3701}
3702
3703SANE_Status
3704sane_start (SANE_Handle handle)
3705{
3706  BH_Scanner *s = handle;
3707  SANE_Status status;
3708
3709  DBG(3, "sane_start called\n");
3710  s->cancelled = SANE_FALSE;
3711
3712  if (s->scanning == SANE_FALSE)
3713    {
3714      /* get preliminary parameters */
3715      status = get_parameters (s, 0);
3716      if (status != SANE_STATUS_GOOD)
3717	{
3718	  DBG (1, "sane_start: get_parameters failed: %s\n",
3719	       sane_strstatus (status));
3720	  return status;
3721	}
3722
3723      /* Do the setup once per 'batch'.  The SANE standard requires the
3724       * frontend to call sane_cancel once all desired frames have been
3725       * acquired.  That is when scanning is set back to SANE_FALSE and
3726       * the 'batch' is considered done.
3727       */
3728      status = start_setup (s);
3729      if (status != SANE_STATUS_GOOD)
3730	{
3731	  DBG (1, "sane_start: start_setup failed: %s\n",
3732	       sane_strstatus (status));
3733	  return status;
3734	}
3735    }
3736
3737  status = start_scan (s);
3738  if (status != SANE_STATUS_GOOD)
3739    {
3740      DBG (1, "sane_start: start_scan failed: %s\n",
3741	   sane_strstatus (status));
3742      return status;
3743    }
3744
3745  return SANE_STATUS_GOOD;
3746}
3747
3748SANE_Status
3749sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
3750{
3751  BH_Scanner *s = handle;
3752  SANE_Status status;
3753  size_t nread;
3754
3755  DBG(3, "sane_read called\n");
3756
3757  *len = 0;
3758
3759  if (s->cancelled) {
3760    DBG (3, "sane_read: cancelled!\n");
3761    return SANE_STATUS_CANCELLED;
3762  }
3763
3764  if (!s->scanning) {
3765    DBG (3, "sane_read: scanning is false!\n");
3766    sane_cancel(s);
3767    return SANE_STATUS_CANCELLED;
3768  }
3769
3770  nread = maxlen;
3771
3772  DBG (3, "sane_read: request %lu bytes\n", (u_long) nread);
3773  /* set InvalidBytes to 0 before read; sense_handler will set it
3774   * to non-zero if we do the last partial read.
3775   */
3776  s->InvalidBytes = 0;
3777  status = read_data (s, buf, &nread);
3778  if (status != SANE_STATUS_GOOD)
3779    {
3780      DBG (1, "sane_read: read_data failed %s\n",
3781	   sane_strstatus(status));
3782      sane_cancel (s);
3783      return status;
3784    }
3785  nread = maxlen - s->InvalidBytes;
3786  DBG (3, "sane_read: got %lu bytes\n", (u_long) nread);
3787  *len = nread;
3788
3789  return (maxlen != 0 && nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_GOOD;
3790}
3791
3792SANE_Status
3793sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
3794{
3795#ifdef NONBLOCKSUPPORTED
3796  BH_Scanner *s = handle;
3797#endif
3798  DBG(3, "sane_set_io_mode called: non_blocking=%d\n", non_blocking);
3799
3800#ifdef NONBLOCKSUPPORTED
3801  if (s->fd < 0)
3802    {
3803      return SANE_STATUS_INVAL;
3804    }
3805
3806  if (fcntl (s->fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
3807    {
3808      DBG(1, "sane_set_io_mode: error setting io mode\n");
3809      return SANE_STATUS_IO_ERROR;
3810    }
3811
3812 return SANE_STATUS_GOOD;
3813#else
3814 (void) handle; /* get rid of compiler warning */
3815 return (non_blocking == 1) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD;
3816#endif
3817}
3818
3819SANE_Status
3820sane_get_select_fd (SANE_Handle handle, SANE_Int *fd)
3821{
3822#ifdef NONBLOCKSUPPORTED
3823  BH_Scanner *s = handle;
3824#endif
3825  DBG(3, "sane_get_select_fd called\n");
3826
3827#ifdef NONBLOCKSUPPORTED
3828  if (s->fd < 0)
3829    {
3830      return SANE_STATUS_INVAL;
3831    }
3832  *fd = s->fd;
3833
3834  return SANE_STATUS_GOOD;
3835#else
3836  (void) handle; (void) fd; /* get rid of compiler warning */
3837  return SANE_STATUS_UNSUPPORTED;
3838#endif
3839}
3840
3841void
3842sane_cancel (SANE_Handle handle)
3843{
3844  BH_Scanner *s = (BH_Scanner *) handle;
3845  DBG(3, "sane_cancel called\n");
3846  if (s->scanning)
3847    {
3848      /* if batchmode is enabled, then call set_window to
3849       * abort the batch
3850       */
3851      if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE)
3852	{
3853	  DBG(5, "sane_cancel: calling set_window to abort batch\n");
3854	  set_window(s, BH_BATCH_ABORT);
3855	}
3856    }
3857  s->scanning = SANE_FALSE;
3858  s->cancelled = SANE_TRUE;
3859}
3860
3861void
3862sane_close (SANE_Handle handle)
3863{
3864  BH_Scanner *s = (BH_Scanner *) handle;
3865  DBG(3, "sane_close called\n");
3866
3867  if (s->fd != -1)
3868    sanei_scsi_close (s->fd);
3869  s->fd = -1;
3870  free (s);
3871}
3872
3873void
3874sane_exit (void)
3875{
3876  BH_Device *dev, *next;
3877  DBG(3, "sane_exit called\n");
3878
3879  for (dev = first_dev; dev; dev = next)
3880    {
3881      next = dev->next;
3882      free (dev);
3883    }
3884
3885  if (devlist)
3886    free (devlist);
3887}
3888