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
67 static const SANE_Device **devlist = 0;
68 static int num_devices = 0;
69 static BH_Device *first_dev = NULL;
70 static BH_Scanner *first_handle = NULL;
71 static SANE_Char inquiry_data[255] = "Bell+Howell scanner";
72 static SANE_Int disable_optional_frames = 0;
73 static SANE_Int fake_inquiry = 0;
74
allblank(const char *s)75 static int allblank(const char *s)
76 {
77 while (s && *s)
78 if (!isspace(*s++))
79 return 0;
80
81 return 1;
82 }
83
84 static size_t
max_string_size(const SANE_String_Const strings[])85 max_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
100 static void
trim_spaces(char *s, size_t n)101 trim_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
111 static SANE_String_Const
print_devtype(SANE_Byte devtype)112 print_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
133 static SANE_String_Const
print_barcodetype(SANE_Int i)134 print_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
141 static SANE_String_Const
print_orientation(SANE_Int i)142 print_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
163 static SANE_String_Const
print_read_type(SANE_Int i)164 print_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
250 static SANE_Int
get_rotation_id(char *s)251 get_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
263 static SANE_Int
get_compression_id(char *s)264 get_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
276 static SANE_Int
get_barcode_id(char *s)277 get_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
289 static SANE_Int
get_scan_mode_id(char *s)290 get_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
302 static SANE_Int
get_paper_id(char *s)303 get_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
315 static SANE_Int
get_barcode_search_mode(char *s)316 get_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
346 static void
appendStdList(BH_Info *sc, SANE_Int res)347 appendStdList(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
354 static void
ScannerDump(BH_Scanner *s)355 ScannerDump(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
451 static SANE_Status
test_unit_ready(int fd)452 test_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
465 static SANE_Status
object_position(BH_Scanner *s)466 object_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
480 static SANE_Status
read_barcode_data(BH_Scanner *s, FILE *fp)481 read_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
565 static SANE_Status
read_icon_data(BH_Scanner *s)566 read_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
603 static SANE_Status
read_barfile(BH_Scanner *s, void *buf, size_t *buf_size)604 read_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
647 static SANE_Status
read_data(BH_Scanner *s, void *buf, size_t *buf_size)648 read_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
672 static SANE_Status
mode_select_measurement(BH_Scanner *s)673 mode_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
699 static SANE_Status
mode_select_timeout(BH_Scanner *s)700 mode_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
725 static SANE_Status
mode_select_icon(BH_Scanner *s)726 mode_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
751 static SANE_Status
mode_select_barcode_priority(BH_Scanner *s)752 mode_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
782 static SANE_Status
mode_select_barcode_param1(BH_Scanner *s)783 mode_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
812 static SANE_Status
mode_select_barcode_param2(BH_Scanner *s)813 mode_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
886 static SANE_Status
mode_select_barcode_param3(BH_Scanner *s)887 mode_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
953 static SANE_Status
inquiry(int fd, void *buf, size_t *buf_size, SANE_Byte evpd, SANE_Byte page_code)954 inquiry (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
971 static SANE_Status
set_window(BH_Scanner *s, SANE_Byte batchmode)972 set_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
1118 static SANE_Status
get_window(BH_Scanner *s, SANE_Int *w, SANE_Int *h, SANE_Bool backpage)1119 get_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
1190 static SANE_Status
get_parameters(SANE_Handle handle, SANE_Parameters *params)1191 get_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
1368 static SANE_Status
section_parse(const char *val, BH_Section *sect, SANE_Int res, SANE_Int comp)1369 section_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
1496 static SANE_Status
setup_sections(BH_Scanner *s, const char *val)1497 setup_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
1547 static SANE_Status
start_setup(BH_Scanner *s)1548 start_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
1819 static SANE_Status
start_scan(BH_Scanner *s)1820 start_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 */
1976 static SANE_Status
sense_handler(int scsi_fd, u_char *result, void *arg)1977 sense_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
2315 static SANE_Status
init_options(BH_Scanner * s)2316 init_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
2842 static SANE_Status
attach(const char *devnam, BH_Device ** devp)2843 attach (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
3140 static SANE_Status
attach_one(const char *devnam)3141 attach_one(const char *devnam)
3142 {
3143 attach (devnam, NULL);
3144 return SANE_STATUS_GOOD;
3145 }
3146
3147 SANE_Status
sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize)3148 sane_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
3234 SANE_Status
sane_get_devices(const SANE_Device ***device_list, SANE_Bool local)3235 sane_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
3258 SANE_Status
sane_open(SANE_String_Const devnam, SANE_Handle *handle)3259 sane_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
3333 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)3334 sane_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
3345 SANE_Status
sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Word *info)3346 sane_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
3669 SANE_Status
sane_get_parameters(SANE_Handle handle, SANE_Parameters *params)3670 sane_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
3703 SANE_Status
sane_start(SANE_Handle handle)3704 sane_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
3748 SANE_Status
sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)3749 sane_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
3792 SANE_Status
sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking)3793 sane_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
3819 SANE_Status
sane_get_select_fd(SANE_Handle handle, SANE_Int *fd)3820 sane_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
3841 void
sane_cancel(SANE_Handle handle)3842 sane_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
3861 void
sane_close(SANE_Handle handle)3862 sane_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
3873 void
sane_exit(void)3874 sane_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