1 /*******************************************************************************
2  * SANE - Scanner Access Now Easy.
3 
4    avision.c
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    *****************************************************************************
39 
40    This file implements a SANE backend for the Avision SCSI Scanners (like the
41    AV 630 / 620 (CS) ...) and some Avision (OEM) USB scanners (like the HP 53xx,
42    74xx, Minolta FS-V1 ...) or Fujitsu ScanPartner with the AVISION SCSI-2/3
43    or USB command set and written by René Rebe and Meino Cramer.
44 
45 
46    Copyright 2002 - 2015 by
47                	"Ren Rebe" <rene@exactcode.de>
48 
49    Copyright 1999, 2000, 2001 by
50                 "René Rebe" <rene@exactcode.de>
51                 "Meino Christian Cramer" <mccramer@s.netic.de>
52 
53    Copyright 2002 by
54                 "Jose Paulo Moitinho de Almeida" <moitinho@civil.ist.utl.pt>
55 
56    Copyright 2010, 2011 by
57                 "Mike Kelly" <mike@piratehaven.org>
58 
59    Additional Contributors:
60                 "Gunter Wagner"
61                   (some fixes and the transparency option)
62                 "Martin Jelínek" <mates@sirrah.troja.mff.cuni.cz>
63                    nice attach debug output
64                 "Marcin Siennicki" <m.siennicki@cloos.pl>
65                    found some typos and contributed fixes for the HP 7400
66                 "Frank Zago" <fzago@greshamstorage.com>
67                    Mitsubishi IDs and report
68                 Avision INC
69                    example code to handle calibration and C5 ASIC specifics
70                 "Franz Bakan" <fbakan@gmx.net>
71                    OS/2 threading support
72                 "Falk Rohsiepe"
73                    Spelling and whitespace as well as HP5370 quirks
74 
75    Many additional special thanks to:
76                 Avision INC for providing protocol documentation.
77                 Avision INC for sponsoring an AV 8000S with ADF.
78                 Avision Europe and BHS Binkert for sponsoring several more scanners.
79                 Archivista GmbH, Switzerland, for sponsoring several features
80                 Roberto Di Cosmo who sponsored a HP 5370 scanner.
81                 Oliver Neukum who sponsored a HP 5300 USB scanner.
82                 Matthias Wiedemann for lending his HP 7450C for some weeks.
83                 Compusoft, C.A. Caracas / Venezuela for sponsoring a
84                            HP 7450 scanner and so enhanced ADF support.
85                 Chris Komatsu for the nice ADF scanning observation.
86 
87                 All the many other beta-tester and debug-log sender!
88 
89                 Thanks to all the people and companies above. Without you
90                 the Avision backend would not be in the shape it is today! ;-)
91 
92 ********************************************************************************/
93 
94 /* SANE-FLOW-DIAGRAMM (from umax.c)
95  *
96  * - sane_init() : initialize backend, attach scanners(devicename,0)
97  * . - sane_get_devices() : query list of scanner-devices
98  * . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev)
99  * . . - sane_set_io_mode : set blocking-mode
100  * . . - sane_get_select_fd : get scanner-fd
101  * . . - sane_get_option_descriptor() : get option information
102  * . . - sane_control_option() : change option values
103  * . .
104  * . . - sane_start() : start image acquisition
105  * . .   - sane_get_parameters() : returns actual scan-parameters
106  * . .   - sane_read() : read image-data (from pipe)
107  *
108  * in ADF mode this is done often:
109  * . . - sane_start() : start image acquisition
110  * . .   - sane_get_parameters() : returns actual scan-parameters
111  * . .   - sane_read() : read image-data (from pipe)
112  *
113  * . . - sane_cancel() : cancel operation, kill reader_process
114  *
115  * . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle
116  * - sane_exit() : terminate use of backend, free devicename and device-structure
117  */
118 
119 #include "../include/sane/config.h"
120 
121 #include <errno.h>
122 #include <fcntl.h>
123 #include <limits.h>
124 #include <signal.h>
125 #include <stdio.h>
126 #include <stdlib.h>
127 #include <string.h>
128 #include <sys/types.h>
129 #include <unistd.h>
130 #include <sys/time.h>
131 
132 #include <math.h>
133 
134 #define BACKEND_NAME avision
135 #define BACKEND_BUILD 297 /* avision backend BUILD version */
136 
137 #include "../include/sane/sane.h"
138 #include "../include/sane/sanei.h"
139 #include "../include/sane/saneopts.h"
140 #include "../include/sane/sanei_thread.h"
141 #include "../include/sane/sanei_scsi.h"
142 #include "../include/sane/sanei_usb.h"
143 #include "../include/sane/sanei_config.h"
144 #include "../include/sane/sanei_backend.h"
145 
146 #include <avision.h>
147 
148 /* For timeval... */
149 #ifdef DEBUG
150 #include <sys/time.h>
151 #endif
152 
153 /* Attention: The comments must stay as they are - they are automatically parsed
154    to generate the SANE avision.desc file, as well as HTML online content! */
155 
156 /* Attention2: This device table is part of the source code and as such
157    licensed under the terms of the license as listed above (GPL2+). By
158    using this data you obviously create derived work! -ReneR */
159 
160 static Avision_HWEntry Avision_Device_List [] =
161   {
162     { "AVISION", "AV100CS",
163       0, 0,
164       "Avision", "AV100CS",
165       0,
166       { 0, {0, 0}, {{0, 0}, {0, 0}} }
167     },
168     /* status="untested" */
169 
170     { "AVISION", "AV100IIICS",
171       0, 0,
172       "Avision", "AV100IIICS",
173       0,
174       { 0, {0, 0}, {{0, 0}, {0, 0}} }
175     },
176     /* status="untested" */
177 
178     { "AVISION", "AV100S",
179       0, 0,
180       "Avision", "AV100S",
181       0,
182       { 0, {0, 0}, {{0, 0}, {0, 0}} }
183     },
184     /* status="untested" */
185 
186     { NULL, NULL,
187       0x0638, 0x0A27,
188       "Avision", "AV120",
189       AV_INT_STATUS,
190       { 0, {0, 0}, {{0, 0}, {0, 0}} }
191     },
192     /* comment="sheetfed scanner" */
193     /* status="complete" */
194 
195     { NULL, NULL,
196       0x0638, 0x0A3C,
197       "Avision", "AV121",
198       AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA,
199       { 0, {0, 0}, {{0, 0}, {0, 0}} }
200     },
201     /* comment="sheetfed scanner" */
202     /* status="good" */
203 
204     { NULL, NULL,
205       0x0638, 0x0A33,
206       "Avision", "AV122",
207       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA,
208       { 0, {0, 0}, {{0, 0}, {-12.7, 0}} }
209     },
210     /* comment="sheetfed duplex scanner" */
211     /* status="good" */
212 
213     { NULL, NULL,
214       0x0638, 0x0A93,
215       "Avision", "AV122 C2",
216       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_NOT_KEEP_WINDOW | AV_DOES_KEEP_GAMMA,
217       { 0, {0, 0}, {{0, 0}, {-12.7, 0}} }
218     },
219     /* comment="sheetfed duplex scanner" */
220     /* status="good" */
221 
222     { NULL, NULL,
223       0x0638, 0x0A24,
224       "Avision", "AV210",
225       AV_INT_BUTTON  | AV_ACCEL_TABLE,
226       { 0, {0, 0}, {{0, 0}, {0, 0}} }
227     },
228     /* comment="sheetfed scanner" */
229     /* status="complete" */
230 
231     { NULL, NULL,
232       0x0638, 0x0A25,
233       "Avision", "AV210",
234       AV_INT_BUTTON  | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN,
235       { 0, {0, 0}, {{0, 0}, {0, 0}} }
236     },
237     /* comment="sheetfed scanner" */
238     /* status="complete" */
239 
240     { NULL, NULL,
241       0x0638, 0x0A3A,
242       "Avision", "AV210C2",
243       AV_INT_BUTTON | AV_GRAY_MODES,
244       { 0, {0, 0}, {{0, 0}, {0, 0}} }
245     },
246     /* comment="sheetfed scanner" */
247     /* status="complete" */
248 
249     { NULL, NULL,
250       0x0638, 0x0A2F,
251       "Avision", "AV210C2-G",
252       AV_INT_BUTTON | AV_GRAY_MODES,
253       { 0, {0, 0}, {{0, 0}, {0, 0}} }
254     },
255     /* comment="sheetfed scanner" */
256     /* status="complete" */
257 
258     { NULL, NULL,
259       0x0638, 0x1A35,
260       "Avision", "AV210D2+",
261       AV_INT_BUTTON | AV_USE_GRAY_FILTER,
262       { 0, {0, 0}, {{0, 0}, {0, 0}} }
263     },
264     /* comment="sheetfed scanner" */
265     /* status="complete" */
266 
267     { NULL, NULL,
268       0x0638, 0x0A23,
269       "Avision", "AV220",
270       AV_INT_BUTTON | AV_GRAY_MODES,
271       { 0, {0, 0}, {{0, 0}, {0, 0}} }
272     },
273     /* comment="duplex! sheetfed scanner" */
274     /* status="complete" */
275 
276     { NULL, NULL,
277       0x0638, 0x0A2A,
278       "Avision", "AV220C2",
279       AV_INT_BUTTON | AV_CANCEL_BUTTON,
280       { 0, {0, 0}, {{0, 0}, {0, 0}} }
281     },
282     /* comment="duplex! sheetfed scanner" */
283     /* status="complete" */
284 
285     { NULL, NULL,
286       0x0638, 0x0A2B,
287       "Avision", "AV220D2",
288       AV_INT_BUTTON | AV_CANCEL_BUTTON,
289       { 0, {0, 0}, {{0, 0}, {0, 0}} }
290     },
291     /* comment="duplex! sheetfed scanner" */
292     /* status="complete" */
293 
294     { NULL, NULL,
295       0x0638, 0x1A31,
296       "Avision", "AV220D2+",
297       AV_INT_BUTTON | AV_CANCEL_BUTTON | AV_USE_GRAY_FILTER,
298       { 0, {0, 0}, {{0, 0}, {0, 0}} }
299     },
300     /* comment="duplex! sheetfed scanner" */
301     /* status="complete" */
302 
303     { NULL, NULL,
304       0x0638, 0x1A33,
305       "Avision", "AV186+",
306       AV_INT_BUTTON | AV_CANCEL_BUTTON | AV_USE_GRAY_FILTER,
307       { 0, {0, 0}, {{0, 0}, {0, 0}} }
308     },
309     /* comment="duplex! sheetfed scanner" */
310     /* status="good" */
311 
312     { NULL, NULL,
313       0x0638, 0x2AD9,
314       "Avision", "AV188",
315       AV_INT_BUTTON | AV_CANCEL_BUTTON | AV_USE_GRAY_FILTER,
316       { 0, {0, 0}, {{0, 0}, {0, 0}} }
317     },
318     /* comment="duplex! sheetfed scanner" */
319     /* status="untested" */
320 
321     { NULL, NULL,
322       0x0638, 0x0A2C,
323       "Avision", "AV220+",
324       AV_INT_BUTTON | AV_CANCEL_BUTTON,
325       { 0, {0, 0}, {{0, 0}, {0, 0}} }
326     },
327     /* comment="duplex! sheetfed scanner" */
328     /* status="complete" */
329 
330     { NULL, NULL,
331       0x0638, 0x0A2D,
332       "Avision", "AV220C2-G",
333       AV_INT_BUTTON | AV_CANCEL_BUTTON,
334       { 0, {0, 0}, {{0, 0}, {0, 0}} }
335     },
336     /* comment="duplex! sheetfed scanner" */
337     /* status="complete" */
338 
339     { NULL, NULL,
340       0x0638, 0x0A2E,
341       "Avision", "AV220C2-B",
342       AV_INT_BUTTON | AV_CANCEL_BUTTON,
343       { 0, {0, 0}, {{0, 0}, {0, 0}} }
344     },
345     /* comment="duplex! sheetfed scanner" */
346     /* status="complete" */
347 
348     { NULL, NULL,
349       0x0638, 0x0A94,
350       "Avision", "AV220-G",
351       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_FIRMWARE,
352       { 0, {0, 0}, {{0, 0}, {0, 0}} }
353     },
354     /* comment="duplex! sheetfed scanner" */
355     /* status="complete" */
356 
357     { "AVISION", "AV240SC",
358       0, 0,
359       "Avision", "AV240SC",
360       0,
361       { 0, {0, 0}, {{0, 0}, {0, 0}} }
362     },
363     /* status="untested" */
364 
365     { "AVISION", "AV260CS",
366       0, 0,
367       "Avision", "AV260CS",
368       0,
369       { 0, {0, 0}, {{0, 0}, {0, 0}} }
370     },
371     /* status="untested" */
372 
373     { "AVISION", "AV360CS",
374       0, 0,
375       "Avision", "AV360CS",
376       0,
377       { 0, {0, 0}, {{0, 0}, {0, 0}} }
378     },
379     /* status="untested" */
380 
381     { "AVISION", "AV363CS",
382       0, 0,
383       "Avision", "AV363CS",
384       0,
385       { 0, {0, 0}, {{0, 0}, {0, 0}} }
386     },
387     /* status="untested" */
388 
389     { "AVISION", "AV420CS",
390       0, 0,
391       "Avision", "AV420CS",
392       0,
393       { 0, {0, 0}, {{0, 0}, {0, 0}} }
394     },
395     /* status="untested" */
396 
397     { "AVISION", "AV6120",
398       0, 0,
399       "Avision", "AV6120",
400       0,
401       { 0, {0, 0}, {{0, 0}, {0, 0}} }
402     },
403     /* status="untested" */
404 
405     { NULL, "AV610",
406       0x0638, 0x0a18,
407       "Avision", "AV610",
408       AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_BUTTON,
409       { 0, {0, 0}, {{0, 0}, {0, 0}} }
410     },
411     /* status="good" */
412 
413     { NULL, NULL,
414       0x0638, 0x0a18,
415       "Avision", "AV600U Plus",
416       /* If this unit requires the AV_INT_STATUS flag, then we'll need to alter the code to deal with two different devices with the same USB id (AV610 above) */
417       AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | /* AV_INT_STATUS | */ AV_INT_BUTTON,
418       { 0, {0, 0}, {{0, 0}, {0, 0}} }
419     },
420     /* status="good" */
421 
422     { NULL, NULL,
423       0x0638, 0x0a5e,
424       "Avision", "AV610C2",
425       AV_NO_BACKGROUND | AV_INT_BUTTON, /* cancel button -> sense abort! */
426       { 0, {0, 0}, {{0, 0}, {0, 0}} }
427     },
428     /* status="good" */
429 
430    { NULL, NULL,
431      0x0638, 0x0a41,
432      "Avision", "AM3000 Series",
433       0,
434       { 0, {0, 0}, {{0, 0}, {0, 0}} }
435     },
436     /* comment="MFD" */
437     /* status="basic" */
438 
439     { NULL, NULL,
440       0x0638, 0x0a16,
441       "Avision", "DS610CU Scancopier",
442       AV_INT_STATUS,
443       { 0, {0, 0}, {{0, 0}, {0, 0}} }
444     },
445     /* comment="1 pass, 600 dpi, A4" */
446     /* status="good" */
447 
448     { "AVISION", "AV620CS",
449       0, 0,
450       "Avision", "AV620CS",
451       0,
452       { 0, {0, 0}, {{0, 0}, {0, 0}} }
453     },
454     /* comment="1 pass, 600 dpi" */
455     /* status="complete" */
456 
457     { "AVISION", "AV620CS Plus",
458       0, 0,
459       "Avision", "AV620CS Plus",
460       0,
461       { 0, {0, 0}, {{0, 0}, {0, 0}} }
462     },
463     /* comment="1 pass, 1200 dpi" */
464     /* status="complete" */
465 
466     { "AVISION", "AV630CS",
467       0, 0,
468       "Avision", "AV630CS",
469       0,
470       { 0, {0, 0}, {{0, 0}, {0, 0}} }
471     },
472     /* comment="1 pass, 1200 dpi" */
473     /* status="complete" */
474 
475     { "AVISION", "AV630CSL",
476       0, 0,
477       "Avision", "AV630CSL",
478       0,
479       { 0, {0, 0}, {{0, 0}, {0, 0}} }
480     },
481     /* comment="1 pass, 1200 dpi" */
482     /* status="untested" */
483 
484     { "AVISION", "AV6240",
485       0, 0,
486       "Avision", "AV6240",
487       0,
488       { 0, {0, 0}, {{0, 0}, {0, 0}} }
489     },
490     /* comment="1 pass, ??? dpi" */
491     /* status="complete" */
492 
493     { NULL, NULL,
494       0x0638, 0x0A13,
495       "Avision", "AV600U",
496       AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON,
497       { 0, {0, 0}, {{0, 0}, {0, 0}} }
498     },
499     /* comment="1 pass, 600 dpi" */
500     /* status="good" */
501 
502     { "AVISION", "AV660S",
503       0, 0,
504       "Avision", "AV660S",
505       0,
506       { 0, {0, 0}, {{0, 0}, {0, 0}} }
507     },
508     /* comment="1 pass, ??? dpi" */
509     /* status="untested" */
510 
511     { "AVISION", "AV680S",
512       0, 0,
513       "Avision", "AV680S",
514       0,
515       { 0, {0, 0}, {{0, 0}, {0, 0}} }
516     },
517     /* comment="1 pass, ??? dpi" */
518     /* status="untested" */
519 
520     { "AVISION", "AV690U",
521       0, 0,
522       "Avision", "AV690U",
523       0,
524       { 0, {0, 0}, {{0, 0}, {0, 0}} }
525     },
526     /* comment="1 pass, 2400 dpi" */
527     /* status="untested" */
528 
529     { "AVISION", "AV800S",
530       0, 0,
531       "Avision", "AV800S",
532       0,
533       { 0, {0, 0}, {{0, 0}, {0, 0}} }
534     },
535     /* comment="1 pass, ??? dpi" */
536     /* status="untested" */
537 
538     { "AVISION", "AV810C",
539       0, 0,
540       "Avision", "AV810C",
541       0,
542       { 0, {0, 0}, {{0, 0}, {0, 0}} }
543     },
544     /* comment="1 pass, ??? dpi" */
545     /* status="untested" */
546 
547     { "AVISION", "AV820",
548       0, 0,
549       "Avision", "AV820",
550       0,
551       { 0, {0, 0}, {{0, 0}, {0, 0}} }
552     },
553     /* comment="1 pass, ??? dpi" */
554     /* status="untested" */
555 
556     { "AVISION", "AV820C",
557       0, 0,
558       "Avision", "AV820C",
559       0,
560       { 0, {0, 0}, {{0, 0}, {0, 0}} }
561     },
562     /* comment="1 pass, ??? dpi" */
563     /* status="complete" */
564 
565     { "AVISION", "AV820C Plus",
566       0, 0,
567       "Avision", "AV820C Plus",
568       0,
569       { 0, {0, 0}, {{0, 0}, {0, 0}} }
570     },
571     /* comment="1 pass, ??? dpi" */
572     /* status="complete" */
573 
574     { "AVISION", "AV830C",
575       0, 0,
576       "Avision", "AV830C",
577       0,
578       { 0, {0, 0}, {{0, 0}, {0, 0}} }
579     },
580     /* comment="1 pass, ??? dpi" */
581     /* status="complete" */
582 
583     { "AVISION", "AV830C Plus",
584       0, 0,
585       "Avision", "AV830C Plus",
586       0,
587       { 0, {0, 0}, {{0, 0}, {0, 0}} }
588     },
589     /* comment="1 pass, ??? dpi" */
590     /* status="untested" */
591 
592     { "AVISION", "AV880",
593       0, 0,
594       "Avision", "AV880",
595       0,
596       { 0, {0, 0}, {{0, 0}, {0, 0}} }
597     },
598     /* comment="1 pass, ??? dpi" */
599     /* status="untested" */
600 
601     { "AVISION", "AV880C",
602       0, 0,
603       "Avision", "AV880C",
604       0,
605       { 0, {0, 0}, {{0, 0}, {0, 0}} }
606     },
607     /* comment="1 pass, ??? dpi" */
608     /* status="untested" */
609 
610     { "AVISION", "AV3200C",
611       0, 0,
612       "Avision", "AV3200C",
613       AV_NON_INTERLACED_DUPLEX_300 | AV_FASTER_WITH_FILTER,
614       { 0, {0, 0}, {{0, 0}, {0, 0}} }
615     },
616     /* comment="1 pass, ??? dpi" */
617     /* status="complete" */
618 
619     { "AVISION", "AV3200SU",
620       0x0638, 0x0A4E,
621       "Avision", "AV3200SU",
622       0,
623       { 0, {0, 0}, {{0, 0}, {0, 0}} }
624     },
625     /* comment="1 pass, ??? dpi" */
626     /* status="complete" */
627 
628     { "AVISION", "AV3730SU",
629       0x0638, 0x0A4F,
630       "Avision", "AV3730SU",
631       0,
632       { 0, {0, 0}, {{0, 0}, {0, 0}} }
633     },
634     /* comment="1 pass, ??? dpi" */
635     /* status="complete" */
636 
637     { "AVISION", "AV3750SU",
638       0x0638, 0x0A65,
639       "Avision", "AV3750SU",
640       0,
641       { 0, {0, 0}, {{0, 0}, {0, 0}} }
642     },
643     /* comment="1 pass, ??? dpi" */
644     /* status="complete" */
645 
646     { "AVISION", "AV3800C",
647       0, 0,
648       "Avision", "AV3800C",
649       0,
650       { 0, {0, 0}, {{0, 0}, {0, 0}} }
651     },
652     /* comment="1 pass, ??? dpi" */
653     /* status="complete" */
654 
655     { "AVISION", "AV3850SU",
656       0x0638, 0x0a66,
657       "Avision", "AV3850SU",
658       0,
659       { 0, {0, 0}, {{0, 0}, {0, 0}} }
660     },
661     /* comment="1 pass, ??? dpi" */
662     /* status="complete" */
663 
664     { "AVISION", "FB6000E",
665       0, 0,
666       "Avision", "FB6000E",
667       AV_NON_INTERLACED_DUPLEX_300,
668       { 0, {0, 0}, {{0, 0}, {0, 0}} }
669     },
670     /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
671     /* status="complete" */
672 
673     { NULL, NULL,
674       0x0638, 0x0a82,
675       "Avision", "FB6080E",
676       AV_NON_INTERLACED_DUPLEX_300,
677       { 0, {0, 0}, {{0, 0}, {0, 0}} }
678     },
679     /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */
680     /* status="complete" */
681 
682     { NULL, NULL,
683       0x0638, 0x0a84,
684       "Avision", "FB2080E",
685       0,
686       { 0, {0, 0}, {{0, 0}, {0, 0}} }
687     },
688     /* comment="1 pass, 600 dpi, zero-edge" ASIC 7 */
689     /* status="basic" */
690 
691     { "AVISION", "AV8000S",
692       0, 0,
693       "Avision", "AV8000S",
694       AV_DOES_NOT_KEEP_WINDOW,
695       { 0, {0, 0}, {{0, 0}, {0, 0}} }
696     },
697     /* comment="1 pass, 1200 dpi, A3" */
698     /* status="complete" */
699 
700     { NULL, NULL,
701       0x0638, 0x0a4d,
702       "Avision", "AV8050U",
703       AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,
704       { 0, {0, 0}, {{0, 0}, {0, 0}} }
705     },
706     /* comment="1 pass, 1200 dpi, A3 - duplex!" */
707     /* status="complete" */
708 
709     { "AVISION", "AV8300",
710       0x0638, 0x0A40,
711       "Avision", "AV8300",
712       AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,
713       { 0, {0, 0}, {{0, 0}, {0, 0}} }
714     },
715     /* comment="1 pass, 1200 dpi, A3 - duplex!" */
716     /* status="complete" */
717 
718     { "AVISION", "AV8350",
719       0x0638, 0x0A68,
720       "Avision", "AV8350",
721       AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA,
722       { 0, {0, 0}, {{0, 0}, {0, 0}} }
723     },
724     /* comment="1 pass, 1200 dpi, A3 - duplex!" */
725     /* status="complete" */
726 
727     { NULL, NULL,
728       0x0638, 0x0A61,
729       "Avision", "IT8300",
730       AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE,
731       { 0, {0, 0}, {{0, 0}, {0, 0}} }
732     },
733     /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */
734     /* status="good" */
735 
736     { NULL, NULL,
737        0x0638, 0x0AA1,
738       "Avision", "@V2500",
739       0,
740       { 0, {0, 0}, {{0, 0}, {0, 0}} }
741     },
742     /* comment="" */
743     /* status="untested" */
744 
745     { NULL, NULL,
746       0x0638, 0x0A45,
747       "Avision", "@V5100",
748       0,
749       { 0, {0, 0}, {{0, 0}, {0, 0}} }
750     },
751     /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */
752     /* status="good" */
753 
754     { "AVISION", "AVA3",
755       0, 0,
756       "Avision", "AVA3",
757       AV_FORCE_A3,
758       { 0, {0, 0}, {{0, 0}, {0, 0}} }
759     },
760     /* comment="1 pass, 600 dpi, A3" */
761     /* status="basic" */
762 
763     /* and possibly more avisions ;-) */
764 
765     { "HP",      "ScanJet 5300C",
766       0x03f0, 0x0701,
767       "Hewlett-Packard", "ScanJet 5300C",
768       AV_INT_STATUS,
769       { 0, {0, 0}, {{0, 0}, {0, 0}} }
770     },
771     /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */
772     /* status="complete" */
773 
774     { "HP",      "ScanJet 5370C",
775       0x03f0, 0x0701,
776       "Hewlett-Packard", "ScanJet 5370C",
777       AV_MULTI_CALIB_CMD | AV_INT_STATUS,
778       { 0, {0, 0}, {{0, 0}, {0, 0}} }
779     },
780     /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */
781     /* status="good" */
782 
783     { "hp",      "scanjet 7400c",
784       0x03f0, 0x0801,
785       "Hewlett-Packard", "ScanJet 7400c",
786       AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS,
787       { 0, {0, 0}, {{0, 0}, {0, 0}} }
788     },
789     /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */
790     /* status="good" */
791 
792 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
793     { "hp",      "scanjet 7450c",
794       0x03f0, 0x0801,
795       "Hewlett-Packard", "ScanJet 7450c",
796       AV_NO_64BYTE_ALIGN | AV_INT_STATUS,
797       { 0, {0, 0}, {{0, 0}, {0, 0}} }
798     },
799     /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */
800     /* status="good" */
801 
802     { "hp",      "scanjet 7490c",
803       0x03f0, 0x0801,
804       "Hewlett-Packard", "ScanJet 7490c",
805       AV_NO_64BYTE_ALIGN | AV_INT_STATUS,
806       { 0, {0, 0}, {{0, 0}, {0, 0}} }
807     },
808     /* comment="1 pass, 1200 dpi - dual USB/SCSI interface" */
809     /* status="good" */
810 
811 #endif
812     { "HP",      "C9930A",
813       0x03f0, 0x0b01,
814       "Hewlett-Packard", "ScanJet 8200",
815       AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE,
816       { 0, {0, 0}, {{0, 0}, {0, 0}} }
817     },
818     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
819     /* status="good" */
820 
821 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
822     { "HP",      "C9930A",
823       0x03f0, 0x0b01,
824       "Hewlett-Packard", "ScanJet 8250",
825       AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE,
826       { 0, {0, 0}, {{0, 0}, {0, 0}} }
827     },
828     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
829     /* status="good" */
830 #endif
831 
832     { "HP", "C9930A",
833       0x03f0, 0x3905,
834       "Hewlett-Packard", "ScanJet 8270",
835       AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE,
836       { 0, {0, 0}, {{0, 0}, {0, 0}} }
837     },
838     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
839     /* status="good" */
840 
841 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
842     { "HP", "C9930A",
843       0x03f0, 0x0b01,
844       "Hewlett-Packard", "ScanJet 8290",
845       AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE,
846       { 0, {0, 0}, {{0, 0}, {0, 0}} }
847     },
848     /* comment="1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" */
849     /* status="good" */
850 
851 #endif
852     { "HP", "C9930A",
853       0x03f0, 0x3805,
854       "Hewlett-Packard", "ScanJet 8300",
855       0,
856       { 0, {0, 0}, {{0, 0}, {0, 0}} }
857     },
858     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
859     /* status="good" */
860 
861 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
862     { "HP", "C9930A",
863       0x03f0, 0x3805,
864       "Hewlett-Packard", "ScanJet 8350",
865       0,
866       { 0, {0, 0}, {{0, 0}, {0, 0}} }
867     },
868     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
869     /* status="good" */
870 
871     { "HP", "C9930A",
872       0x03f0, 0x3805,
873       "Hewlett-Packard", "ScanJet 8390",
874       0,
875       { 0, {0, 0}, {{0, 0}, {0, 0}} }
876     },
877     /* comment="1 pass, 4800 (?) dpi - USB 2.0" */
878     /* status="good" */
879 
880 #endif
881     { "Minolta", "#2882",
882       0, 0,
883       "Minolta", "Dimage Scan Dual I",
884       AV_FORCE_FILM | AV_NO_START_SCAN, /* not AV_FILMSCANNER (no frame control) */
885       { 0, {0, 0}, {{0, 0}, {0, 0}} }
886     },
887     /* status="basic" */
888 
889     { "Minolta", "#2887",
890       0, 0,
891       "Minolta", "Scan Multi Pro",
892       AV_FORCE_FILM | AV_NO_START_SCAN, /* not AV_FILMSCANNER (no frame control) */
893       { 0, {0, 0}, {{0, 0}, {0, 0}} }
894     },
895     /* status="untested" */
896 
897     { "MINOLTA", "FS-V1",
898       0x0638, 0x026a,
899       "Minolta", "Dimage Scan Dual II",
900       AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_12_BIT_MODE,
901       { 0, {0, 0}, {{0, 0}, {0, 0}} }
902     },
903     /* comment="1 pass, film-scanner" */
904     /* status="good" */
905 
906     { "MINOLTA", "Elite II",
907       0x0686, 0x4004,
908       "Minolta", "Elite II",
909       AV_FILMSCANNER | AV_ONE_CALIB_CMD,
910       { 0, {0, 0}, {{0, 0}, {0, 0}} }
911     },
912     /* comment="1 pass, film-scanner" */
913     /* status="untested" */
914 
915     { "MINOLTA", "FS-V3",
916       0x0686, 0x400d,
917       "Minolta", "Dimage Scan Dual III",
918       AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE,
919       { 0, {0, 0}, {{0, 0}, {0, 0}} }
920     },
921     /* comment="1 pass, film-scanner" */
922     /* status="good" */
923 
924     { "MINOLTA", "FS-V4",
925       0x0686, 0x400e,
926       "Minolta", "Dimage Scan Elite 5400",
927       AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN,
928       { 0, {0, 0}, {{0, 0}, {0, 0}} }
929     },
930     /* comment="1 pass, film-scanner" */
931     /* status="good" */
932 
933     { "QMS", "SC-110",
934       0x0638, 0x0a15,
935       "Minolta-QMS", "SC-110",
936       0,
937       { 0, {0, 0}, {{0, 0}, {0, 0}} }
938     },
939     /* comment="" */
940     /* status="untested" */
941 
942     { "QMS", "SC-215",
943       0x0638, 0x0a16,
944       "Minolta-QMS", "SC-215",
945       0,
946       { 0, {0, 0}, {{0, 0}, {0, 0}} }
947     },
948     /* comment="" */
949     /* status="good" */
950 
951     { "MITSBISH", "MCA-ADFC",
952       0, 0,
953       "Mitsubishi", "MCA-ADFC",
954       0,
955       { 0, {0, 0}, {{0, 0}, {0, 0}} }
956     },
957     /* status="untested" */
958 
959     { "MITSBISH", "MCA-S1200C",
960       0, 0,
961       "Mitsubishi", "S1200C",
962       0,
963       { 0, {0, 0}, {{0, 0}, {0, 0}} }
964     },
965     /* status="untested" */
966 
967     { "MITSBISH", "MCA-S600C",
968       0, 0,
969       "Mitsubishi", "S600C",
970       0,
971       { 0, {0, 0}, {{0, 0}, {0, 0}} }
972     },
973     /* status="untested" */
974 
975     { "MITSBISH", "SS600",
976       0, 0,
977       "Mitsubishi", "SS600",
978       0,
979       { 0, {0, 0}, {{0, 0}, {0, 0}} }
980     },
981     /* status="good" */
982 
983     /* The next are all untested ... */
984 
985     { "FCPA", "ScanPartner",
986       0, 0,
987       "Fujitsu", "ScanPartner",
988       AV_FUJITSU,
989       { 0, {0, 0}, {{0, 0}, {0, 0}} }
990     },
991     /* status="untested" */
992 
993     { "FCPA", "ScanPartner 10",
994       0, 0,
995       "Fujitsu", "ScanPartner 10",
996       AV_FUJITSU,
997       { 0, {0, 0}, {{0, 0}, {0, 0}} }
998     },
999     /* status="untested" */
1000 
1001     { "FCPA", "ScanPartner 10C",
1002       0, 0,
1003       "Fujitsu", "ScanPartner 10C",
1004       AV_FUJITSU,
1005       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1006     },
1007     /* status="untested" */
1008 
1009     { "FCPA", "ScanPartner 15C",
1010       0, 0,
1011       "Fujitsu", "ScanPartner 15C",
1012       AV_FUJITSU,
1013       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1014     },
1015     /* status="untested" */
1016 
1017     { "FCPA", "ScanPartner 300C",
1018       0, 0,
1019       "Fujitsu", "ScanPartner 300C",
1020       0,
1021       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1022     },
1023     /* status="untested" */
1024 
1025     { "FCPA", "ScanPartner 600C",
1026       0, 0,
1027       "Fujitsu", "ScanPartner 600C",
1028       0,
1029       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1030     },
1031     /* status="untested" */
1032 
1033     { "FCPA", "ScanPartner 620C",
1034       0, 0,
1035       "Fujitsu", "ScanPartner 620C",
1036       AV_LIGHT_CHECK_BOGUS,
1037       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1038     },
1039     /* status="good" */
1040 
1041     { "FCPA", "ScanPartner Jr",
1042       0, 0,
1043       "Fujitsu", "ScanPartner Jr",
1044       0,
1045       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1046     },
1047     /* status="untested" */
1048 
1049     { "FCPA", "ScanStation",
1050       0, 0,
1051       "Fujitsu", "ScanStation",
1052       0,
1053       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1054     },
1055     /* status="untested" */
1056 
1057     { NULL, NULL,
1058       0x04c5, 0x1029,
1059       "Fujitsu", "fi-4010CU",
1060       0,
1061       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1062     },
1063     /* status="untested" */
1064 
1065     { NULL, NULL,
1066       0x04c5, 0x10ef,
1067       "Fujitsu", "fi-5015C",
1068       0,
1069       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1070     },
1071     /* status="good" */
1072 
1073     { NULL, NULL,
1074       0x040a, 0x6001,
1075       "Kodak", "i30",
1076       AV_INT_BUTTON | AV_GRAY_MODES,
1077       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1078     },
1079     /* status="untested" */
1080 
1081     { NULL, NULL,
1082       0x040a, 0x6002,
1083       "Kodak", "i40",
1084       AV_INT_BUTTON | AV_GRAY_MODES,
1085       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1086     },
1087     /* status="basic" */
1088 
1089     { NULL, NULL,
1090       0x040a, 0x6003,
1091       "Kodak", "i50",
1092       AV_INT_BUTTON,
1093       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1094     },
1095     /* status="untested" */
1096 
1097 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
1098     { NULL, NULL,
1099       0x040a, 0x6003,
1100       "Kodak", "i55",
1101       AV_INT_BUTTON,
1102       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1103     },
1104     /* status="untested" */
1105 #endif
1106 
1107     { NULL, NULL,
1108       0x040a, 0x6004,
1109       "Kodak", "i60",
1110       AV_INT_BUTTON,
1111       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1112     },
1113     /* status="untested" */
1114 
1115 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
1116     { NULL, NULL,
1117       0x040a, 0x6004,
1118       "Kodak", "i65",
1119       AV_INT_BUTTON,
1120       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1121     },
1122     /* status="untested" */
1123 #endif
1124 
1125     { NULL, NULL,
1126       0x040a, 0x6005,
1127       "Kodak", "i80",
1128       AV_INT_BUTTON,
1129       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1130     },
1131      /* status="good" */
1132 
1133     { NULL, NULL,
1134       0x040a, 0x6013,
1135       "Kodak", "i1120",
1136       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_USE_GRAY_FILTER | AV_SOFT_SCALE |
1137       AV_FORCE_CALIB | AV_NO_QSCAN_MODE | AV_NO_QCALIB_MODE | AV_OVERSCAN_OPTDPI |
1138       AV_NO_REAR | AV_FASTFEED_ON_CANCEL | AV_GAMMA_10 | AV_MULTI_SHEET_SCAN,
1139       { /* offsets */
1140         -1.5, /* first sheet (should be identical for single / duplex) */
1141         {2.5, -6.0}, /* front-only scan */
1142         {{2.0, -14.0}, {-10.0, -2.0}} /* duplex scan */
1143       }
1144     },
1145       /* comment="duplex sheetfed scanner" */
1146       /* status="good" */
1147       /* This is a Kodak OEM device manufactured by avision.
1148          It uses an Avision firmware modified by Kodak, so
1149          some modifications needed to be done here. */
1150 
1151     { "iVina", "1200U",
1152       0x0638, 0x0268,
1153       "iVina", "1200U",
1154       0,
1155       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1156     },
1157     /* status="untested" */
1158 
1159     { NULL, NULL,
1160       0x04a7, 0x0424,
1161       "Visioneer", "Strobe XP 450",
1162       AV_INT_BUTTON  | AV_ACCEL_TABLE,
1163       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1164     },
1165       /* comment="sheetfed scanner" */
1166       /* status="complete" */
1167 
1168     { NULL, NULL,
1169       0x04a7, 0x0491,
1170       "Visioneer", "Strobe XP 450-G",
1171       AV_INT_BUTTON  | AV_ACCEL_TABLE,
1172       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1173     },
1174       /* comment="sheetfed scanner" */
1175       /* status="complete" */
1176 
1177     { NULL, NULL,
1178       0x04a7, 0x0479,
1179       "Visioneer", "Strobe XP 470",
1180       AV_INT_BUTTON  | AV_ACCEL_TABLE,
1181       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1182     },
1183       /* comment="sheetfed scanner" */
1184       /* status="complete" */
1185 
1186     { NULL, NULL,
1187       0x04a7, 0x048F,
1188       "Visioneer", "Strobe XP 470-G",
1189       AV_INT_BUTTON  | AV_ACCEL_TABLE,
1190       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1191     },
1192       /* comment="sheetfed scanner" */
1193       /* status="complete" */
1194 
1195     { NULL, NULL,
1196       0x04a7, 0x0420,
1197       "Visioneer", "9320",
1198       0,
1199       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1200     },
1201       /* comment="sheetfed scanner" */
1202       /* status="complete" */
1203 
1204     { NULL, NULL,
1205       0x04a7, 0x0421,
1206       "Visioneer", "9450",
1207       AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_NO_BUTTON | AV_NO_TUNE_SCAN_LENGTH,
1208       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1209     },
1210       /* comment="sheetfed scanner" */
1211       /* status="complete" */
1212 
1213     { NULL, NULL,
1214       0x04a7, 0x047A,
1215       "Visioneer", "9450-G",
1216       0,
1217       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1218     },
1219       /* comment="sheetfed scanner" */
1220       /* status="complete" */
1221 
1222     { NULL, NULL,
1223       0x04a7, 0x0422,
1224       "Visioneer", "9550",
1225       0,
1226       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1227     },
1228       /* comment="sheetfed scanner" */
1229       /* status="complete" */
1230 
1231     { NULL, NULL,
1232       0x04a7, 0x0390,
1233       "Visioneer", "9650",
1234       0,
1235       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1236     },
1237       /* comment="sheetfed scanner" */
1238       /* status="complete" */
1239 
1240     { NULL, NULL,
1241       0x04a7, 0x047B,
1242       "Visioneer", "9650-G",
1243       0,
1244       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1245     },
1246       /* comment="sheetfed scanner" */
1247       /* status="complete" */
1248 
1249     { NULL, NULL,
1250       0x04a7, 0x0423,
1251       "Visioneer", "9750",
1252       AV_INT_BUTTON,
1253       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1254     },
1255       /* comment="sheetfed scanner" */
1256       /* status="complete" */
1257 
1258     { NULL, NULL,
1259       0x04a7, 0x0493,
1260       "Visioneer", "9750-G",
1261       AV_INT_BUTTON,
1262       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1263     },
1264       /* comment="sheetfed scanner" */
1265       /* status="complete" */
1266 
1267     { NULL, NULL,
1268       0x04a7, 0x0497,
1269       "Visioneer", "Patriot 430",
1270       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA,
1271       { 0, {0, 0}, {{0, 0}, {-12.7, 0}} }
1272     },
1273       /* comment="sheetfed scanner" */
1274       /* status="complete" */
1275 
1276 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
1277     { NULL, NULL,
1278       0x04a7, 0x048F,
1279       "Visioneer", "Patriot 470",
1280       AV_INT_BUTTON,
1281       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1282     },
1283       /* comment="sheetfed scanner" */
1284       /* status="complete" */
1285 #endif
1286 
1287     { NULL, NULL,
1288       0x04a7, 0x0498,
1289       "Visioneer", "Patriot 680",
1290       AV_INT_BUTTON,
1291       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1292     },
1293       /* comment="sheetfed scanner" */
1294       /* status="complete" */
1295 
1296     { NULL, NULL,
1297       0x04a7, 0x0499,
1298       "Visioneer", "Patriot 780",
1299       AV_INT_BUTTON,
1300       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1301     },
1302       /* comment="sheetfed scanner" */
1303       /* status="complete" */
1304 
1305     { NULL, NULL,
1306       0x04a7, 0x049C,
1307       "Xerox", "DocuMate150",
1308       AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK,
1309       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1310     },
1311     /* status="good" */
1312 
1313     { NULL, NULL,
1314       0x04a7, 0x0477,
1315       "Xerox", "DocuMate152",
1316       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK,
1317       { 0, {0, 0}, {{0, 0}, {-12.7, 0}} }
1318     },
1319     /* status="good" */
1320 
1321     { NULL, NULL,
1322       0x04a7, 0x049D,
1323       "Xerox", "DocuMate162",
1324       AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK,
1325       { 0, {0, 0}, {{0, 0}, {-12.7, 0}} }
1326     },
1327     /* status="good" */
1328 
1329     { NULL, NULL,
1330       0x04a7, 0x0448,
1331       "Xerox", "DocuMate250",
1332       AV_INT_BUTTON,
1333       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1334     },
1335     /* status="good" */
1336 
1337     { NULL, NULL,
1338       0x04a7, 0x0490,
1339       "Xerox", "DocuMate250-G",
1340       AV_INT_BUTTON,
1341       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1342     },
1343     /* status="good" */
1344 
1345     { NULL, NULL,
1346       0x04a7, 0x0449,
1347       "Xerox", "DocuMate252",
1348       AV_INT_BUTTON,
1349       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1350     },
1351     /* status="good" */
1352 
1353     { NULL, NULL,
1354       0x04a7, 0x048C,
1355       "Xerox", "DocuMate252-G",
1356       AV_INT_BUTTON,
1357       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1358     },
1359     /* status="good" */
1360 
1361     { NULL, NULL,
1362       0x04a7, 0x0476,
1363       "Xerox", "DocuMate232",
1364       AV_INT_BUTTON,
1365       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1366     },
1367     /* status="good" */
1368 
1369     { NULL, NULL,
1370       0x04a7, 0x044c,
1371       "Xerox", "DocuMate262",
1372       AV_INT_BUTTON,
1373       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1374     },
1375     /* status="good" */
1376 
1377     { NULL, NULL,
1378       0x04a7, 0x048D,
1379       "Xerox", "DocuMate262-G",
1380       AV_INT_BUTTON,
1381       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1382     },
1383     /* status="good" */
1384 
1385     { NULL, NULL,
1386       0x04a7, 0x04a7,
1387       "Xerox", "DocuMate262i",
1388       AV_INT_BUTTON,
1389       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1390     },
1391     /* status="good" */
1392 
1393     { NULL, NULL,
1394       0x04a7, 0x0475,
1395       "Xerox", "DocuMate272",
1396       AV_INT_BUTTON,
1397       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1398     },
1399     /* status="untested" */
1400 
1401     { NULL, NULL,
1402       0x04a7, 0x048E,
1403       "Xerox", "DocuMate272-G",
1404       AV_INT_BUTTON,
1405       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1406     },
1407     /* status="untested" */
1408 
1409     { NULL, NULL,
1410       0x04a7, 0x0446,
1411       "Xerox", "DocuMate510",
1412       AV_INT_BUTTON,
1413       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1414     },
1415     /* status="untested" */
1416 
1417     { NULL, NULL,
1418       0x04a7, 0x0495,
1419       "Xerox", "DocuMate512",
1420       AV_INT_BUTTON,
1421       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1422     },
1423     /* status="untested" */
1424 
1425     { NULL, NULL,
1426       0x04a7, 0x047c,
1427       "Xerox", "DocuMate510-G",
1428       AV_INT_BUTTON,
1429       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1430     },
1431     /* status="untested" */
1432 
1433     { NULL, NULL,
1434       0x04a7, 0x0447,
1435       "Xerox", "DocuMate520",
1436       AV_INT_BUTTON,
1437       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1438     },
1439     /* status="untested" */
1440 
1441     { NULL, NULL,
1442       0x04a7, 0x0492,
1443       "Xerox", "DocuMate520-G",
1444       AV_INT_BUTTON,
1445       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1446     },
1447     /* status="untested" */
1448 
1449 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
1450     { NULL, NULL,
1451       0x04a7, 0x0498,
1452       "Xerox", "DocuMate632",
1453       AV_INT_BUTTON,
1454       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1455     },
1456     /* status="untested" */
1457 #endif
1458 
1459     { NULL, NULL,
1460       0x04a7, 0x0478,
1461       "Xerox", "DocuMate752",
1462       AV_INT_BUTTON,
1463       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1464     },
1465     /* status="untested" */
1466 
1467     { NULL, NULL,
1468       0x04a7, 0x049A,
1469       "Xerox", "DocuMate752",
1470       AV_INT_BUTTON,
1471       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1472     },
1473     /* status="untested" */
1474 
1475 #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION
1476     { NULL, NULL,
1477       0x0638, 0x0a16,
1478       "OKI", "S700 Scancopier",
1479       0,
1480       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1481     },
1482     /* comment="1 pass, 600 dpi, A4" */
1483     /* status="good" */
1484 #endif
1485 
1486     { "B+H", "2000F",
1487       0, 0,
1488       "Bell+Howell", "2000F",
1489       0,
1490       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1491     },
1492     /* comment="1 pass, ??? dpi, A4" */
1493     /* status="basic" */
1494 
1495     { NULL, NULL,
1496       0x0482, 0x0335,
1497       "Kyocera", "FS-1016MFP",
1498       0,
1499       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1500     },
1501     /* comment="1 pass, ??? dpi, A4" */
1502     /* status="untested" */
1503 
1504     /* More IDs from the Avision dll:
1505        ArtiScan ProA3
1506        FB1065
1507        FB1265
1508        PHI860S
1509        PSDC SCSI
1510        SCSI Scan 19200
1511        V6240 */
1512 
1513     /* Possibly:
1514 Lexmark 4600 MFP Option MFP Options
1515 Lexmark 4600 MFP Option (C772n) MFP Options
1516 Lexmark X215
1517 Lexmark Optra Image X242
1518 Lexmark X443
1519 Lexmark 3100
1520 Lexmark 3200
1521 Lexmark X340 MFP Multifunction
1522 Lexmark X342n MFP Multifunction
1523 Lexmark X522
1524 Lexmark X630
1525 Lexmark X632E
1526 Lexmark X642e MFP Multifunction
1527 Lexmark X644e MFP Multifunction
1528 Lexmark X646dte MFP Multifunction
1529 Lexmark X646e MFP Multifunction
1530 Lexmark X646ef MFP Multifunction
1531 Lexmark X772e Multifunction
1532 Lexmark X850e MFP Multifunction
1533 Lexmark X852e MFP Multifunction
1534 Lexmark X854e MFP Multifunction
1535 Lexmark X4500 MFP
1536      */
1537 
1538     /* last entry detection */
1539     { NULL, NULL,
1540       0, 0,
1541       NULL, NULL,
1542       0,
1543       { 0, {0, 0}, {{0, 0}, {0, 0}} }
1544     }
1545   };
1546 
1547 #if 0
1548   struct timeval tv;
1549   #define TIMING(txt) gettimeofday (&tv, NULL);				\
1550   DBG (4, "%lu: " txt "\n", tv.tv_sec * 1000000 + tv.tv_usec)
1551 #else
1552   #define TIMING(txt)
1553 #endif
1554 
1555 /* used when scanner returns invalid range fields ... */
1556 #define A4_X_RANGE 8.5 /* or 8.25 ? */
1557 #define A4_Y_RANGE 11.8
1558 #define A3_X_RANGE 11.8
1559 #define A3_Y_RANGE 16.5 /* or 17 ? */
1560 #define FILM_X_RANGE 1.0 /* really ? */
1561 #define FILM_Y_RANGE 1.0
1562 #define SHEETFEED_Y_RANGE 14.0
1563 
1564 #define AVISION_CONFIG_FILE "avision.conf"
1565 
1566 #define STD_INQUIRY_SIZE 0x24
1567 #define AVISION_INQUIRY_SIZE_V1 0x60
1568 #define AVISION_INQUIRY_SIZE_V2 0x88
1569 #define AVISION_INQUIRY_SIZE_MAX AVISION_INQUIRY_SIZE_V2
1570 
1571 
1572 #define AVISION_BASE_RES 300
1573 
1574 /* calibration (shading) defines */
1575 
1576 #define INVALID_WHITE_SHADING   0x0000
1577 #define DEFAULT_WHITE_SHADING   0xFFF0
1578 
1579 #define MAX_WHITE_SHADING       0xFFFF
1580 /* originally the WHITE_MAP_RANGE was 0x4000 - but this always
1581  * resulted in slightly too dark images - thus I have chosen
1582  * 0x4FFF ... */
1583 #define WHITE_MAP_RANGE         0x4FFF
1584 
1585 #define INVALID_DARK_SHADING    0xFFFF
1586 #define DEFAULT_DARK_SHADING    0x0000
1587 
1588 #define read_constrains(s,var) {\
1589 	if (s->hw->hw->feature_type & AV_NO_64BYTE_ALIGN) {\
1590 		if (var % 64 == 0) var /= 2;\
1591 		if (var % 64 == 0) var += 2;\
1592 	}\
1593 }\
1594 
1595 static int num_devices;
1596 static Avision_Device* first_dev;
1597 static Avision_Scanner* first_handle;
1598 static const SANE_Device** devlist = 0;
1599 
1600 /* this is a bit hacky to get extra information in the attach callback */
1601 static Avision_HWEntry* attaching_hw = 0;
1602 
1603 /* disable the usage of a custom gamma-table */
1604 static SANE_Bool disable_gamma_table = SANE_FALSE;
1605 
1606 /* disable the calibration */
1607 static SANE_Bool disable_calibration = SANE_FALSE;
1608 static SANE_Bool force_calibration = SANE_FALSE;
1609 
1610 /* force scanable areas to ISO(DIN) A4/A3 */
1611 static SANE_Bool force_a4 = SANE_FALSE;
1612 static SANE_Bool force_a3 = SANE_FALSE;
1613 
1614 /* trust ADF-presence flag, even if ADF model is nonzero */
1615 static SANE_Bool skip_adf = SANE_FALSE;
1616 
1617 /* hardware resolutions to interpolate from */
1618 static const int  hw_res_list_c5[] =
1619   {
1620     /* tested on AV600U */
1621     75, 150, 300, 600, 1200, 2400, 4800, /* ... */ 0
1622   };
1623 static const int  hw_res_list_generic[] =
1624   {
1625     50, /* slower than 150 on the AV122/DM152, left for USB 1 host's preview */
1626     75, /* slower than 150 on the AV122/DM152, left for USB 1 host's */
1627     150, 200, 300,
1628     /* 400,*/ /* AV122 simplex y-scaling and duplex interlacing corrupt */
1629     600, 1200, 2400, 4800,
1630     /* ... */
1631     0
1632   };
1633 
1634 static SANE_Bool static_calib_list[3] =
1635   {
1636     SANE_FALSE, SANE_FALSE, SANE_FALSE
1637   };
1638 
1639 static const SANE_Range u8_range =
1640   {
1641     0, /* minimum */
1642     255, /* maximum */
1643     0 /* quantization */
1644   };
1645 
1646 static const SANE_Range percentage_range =
1647   {
1648     SANE_FIX (-100), /* minimum */
1649     SANE_FIX (100), /* maximum */
1650     SANE_FIX (1) /* quantization */
1651   };
1652 
1653 static const SANE_Range exposure_range =
1654   {
1655     0, /* minimum */
1656     1000, /* maximum */
1657     1 /* quantization */
1658   };
1659 
1660 static const SANE_Range overscan_range =
1661   {
1662     SANE_FIX (0), /* minimum */
1663     SANE_FIX (4), /* maximum */ /* 4mm, measured on AV122, AV220C2, i40 */
1664     0 /* quantization */
1665   };
1666 
1667 /* The 0x32 is a random guess based on USB logs. Might need a
1668    per-device value in the future - 0x32 was tested on the AV122,
1669    DM152, AV220. */
1670 static const SANE_Range background_range =
1671   {
1672     0, /* minimum */
1673     0x32, /* maximum */
1674     0 /* quantization */
1675   };
1676 
1677 static const uint8_t test_unit_ready[] =
1678   {
1679     AVISION_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00
1680   };
1681 
1682 /* Remove #ifdef and this comment when this SCSI command is used for
1683    something.  Keeping this definition around so we don't loose info
1684    about the protocol.
1685  */
1686 #ifdef ENABLE_AVISION_SCSI_GET_DATA_STATUS
1687 static const uint8_t get_status[] =
1688   {
1689     AVISION_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00,
1690     0x00, 0x00, 0x0c, 0x00
1691   };
1692 #endif
1693 
1694 static size_t
max_string_size(const SANE_String_Const strings[])1695 max_string_size (const SANE_String_Const strings[])
1696 {
1697   size_t size, max_size = 0;
1698   int i;
1699 
1700   DBG (3, "max_string_size:\n");
1701 
1702   for (i = 0; strings[i]; ++ i) {
1703     size = strlen (strings[i]) + 1;
1704     if (size > max_size)
1705       max_size = size;
1706   }
1707   return max_size;
1708 }
1709 
1710 static SANE_Status
constrain_value(Avision_Scanner * s,SANE_Int option,void * value,SANE_Int * info)1711 constrain_value (Avision_Scanner* s, SANE_Int option, void* value,
1712 		 SANE_Int* info)
1713 {
1714   DBG (3, "constrain_value:\n");
1715   return sanei_constrain_value (s->opt + option, value, info);
1716 }
1717 
debug_print_raw(int dbg_level,char * info,const uint8_t * data,size_t count)1718 static void debug_print_raw (int dbg_level, char* info, const uint8_t* data,
1719 			     size_t count)
1720 {
1721   size_t i;
1722 
1723   DBG (dbg_level, "%s", info);
1724   for (i = 0; i < count; ++ i) {
1725     DBG (dbg_level, "  [%lu] %1d%1d%1d%1d%1d%1d%1d%1db %3oo %3dd %2xx\n",
1726 	 (u_long) i,
1727 	 BIT(data[i],7), BIT(data[i],6), BIT(data[i],5), BIT(data[i],4),
1728 	 BIT(data[i],3), BIT(data[i],2), BIT(data[i],1), BIT(data[i],0),
1729 	 data[i], data[i], data[i]);
1730   }
1731 }
1732 
debug_print_hex_raw(int dbg_level,char * info,const uint8_t * data,size_t count)1733 static void debug_print_hex_raw (int dbg_level, char* info, const uint8_t* data,
1734 				 size_t count)
1735 {
1736   int address = 0;
1737   char text [16*3+1];
1738 
1739   DBG (dbg_level, "%s", info);
1740   while (count) {
1741     char* t = text;
1742     int i = 0;
1743     while (i < 16 && count) {
1744       t += sprintf (t, "%02x ", *data++);
1745       count--; i++;
1746     }
1747     *--t = 0;
1748 
1749     DBG (dbg_level, "  [%08x] %s\n", address, text);
1750     address += 16;
1751   }
1752 }
1753 
debug_print_nvram_data(int dbg_level,char * func,nvram_data * nvram)1754 static void debug_print_nvram_data (int dbg_level, char* func,
1755 				    nvram_data* nvram)
1756 {
1757   DBG (dbg_level, "%s: pad scans:             %d\n",
1758        func, get_quad(nvram->pad_scans));
1759   DBG (dbg_level, "%s: ADF simplex scans:     %d\n",
1760        func, get_quad(nvram->adf_simplex_scans));
1761   DBG (dbg_level, "%s: ADF duplex scans:      %d\n",
1762        func, get_quad(nvram->adf_duplex_scans));
1763   DBG (dbg_level, "%s: flatbed scans:         %d\n",
1764        func, get_quad(nvram->flatbed_scans));
1765 
1766   DBG (dbg_level, "%s: flatbed leading edge:  %d\n",
1767        func, (int16_t)get_double(nvram->flatbed_leading_edge));
1768   DBG (dbg_level, "%s: flatbed side edge:     %d\n",
1769        func, (int16_t)get_double(nvram->flatbed_side_edge));
1770   DBG (dbg_level, "%s: ADF leading edge:      %d\n",
1771        func, (int16_t)get_double(nvram->adf_leading_edge));
1772   DBG (dbg_level, "%s: ADF side edge:         %d\n",
1773        func, (int16_t)get_double(nvram->adf_side_edge));
1774   DBG (dbg_level, "%s: ADF rear leading edge: %d\n",
1775        func, (int16_t)get_double(nvram->adf_rear_leading_edge));
1776   DBG (dbg_level, "%s: ADF rear side edge:    %d\n",
1777        func, (int16_t)get_double(nvram->adf_rear_side_edge));
1778 
1779   DBG (dbg_level, "%s: born month:            %d\n",
1780        func, get_double(nvram->born_month));
1781   DBG (dbg_level, "%s: born day:              %d\n",
1782        func, get_double(nvram->born_day));
1783   DBG (dbg_level, "%s: born year:             %d\n",
1784        func, get_double(nvram->born_year));
1785 
1786   DBG (dbg_level, "%s: first scan month:      %d\n",
1787        func, get_double(nvram->first_scan_month));
1788   DBG (dbg_level, "%s: first scan day:        %d\n",
1789        func, get_double(nvram->first_scan_day));
1790   DBG (dbg_level, "%s: first scan year:       %d\n",
1791        func, get_double(nvram->first_scan_year));
1792 
1793 
1794   DBG (dbg_level, "%s: vert. magnification:   %d\n",
1795        func, get_double(nvram->vertical_magnification));
1796   DBG (dbg_level, "%s: horiz. magnification:  %d\n",
1797        func, get_double(nvram->horizontal_magnification));
1798 
1799   DBG (dbg_level, "%s: CCD type:              %d\n",
1800        func, nvram->ccd_type);
1801   DBG (dbg_level, "%s: scan speed:            %d\n",
1802        func, nvram->scan_speed);
1803 
1804   DBG (dbg_level, "%s: serial:                '%.24s'\n", /* 24 chars max */
1805        func, nvram->serial);
1806 
1807   DBG (dbg_level, "%s: power saving time:     %d\n",
1808        func, get_double(nvram->power_saving_time));
1809 
1810   DBG (dbg_level, "%s: auto feed:             %d\n",
1811        func, nvram->auto_feed);
1812 
1813   DBG (dbg_level, "%s: roller count:          %d\n",
1814        func, get_quad(nvram->roller_count));
1815   DBG (dbg_level, "%s: multifeed count:       %d\n",
1816        func, get_quad(nvram->multifeed_count));
1817   DBG (dbg_level, "%s: jam count:             %d\n",
1818        func, get_quad(nvram->jam_count));
1819 
1820   DBG (dbg_level, "%s: identify info:         '%.16s'\n", /* 16 chars max */
1821        func, nvram->identify_info);
1822   DBG (dbg_level, "%s: formal_name:           '%.16s'\n", /* 16 chars max */
1823        func, nvram->formal_name);
1824 }
1825 
debug_print_avdimen(int dbg_level,char * func,Avision_Dimensions * avdimen)1826 static void debug_print_avdimen (int dbg_level, char* func,
1827 				 Avision_Dimensions* avdimen)
1828 {
1829   DBG (dbg_level, "%s: hw_xres: %d, hw_yres: %d, line_difference: %d\n",
1830        func, avdimen->hw_xres, avdimen->hw_yres, avdimen->line_difference);
1831 
1832   DBG (dbg_level, "%s: tlx: %ld, tly: %ld, brx: %ld, bry: %ld\n",
1833        func, avdimen->tlx, avdimen->tly,
1834        avdimen->brx, avdimen->bry);
1835 
1836   DBG (dbg_level, "%s: hw_pixel_per_line: %d, hw_lines: %d, hw_bytes_per_line: %d\n",
1837        func, avdimen->hw_pixels_per_line, avdimen->hw_lines, avdimen->hw_bytes_per_line);
1838 
1839   DBG (dbg_level, "%s: xres: %d, yres: %d\n",
1840        func, avdimen->xres, avdimen->yres);
1841 }
1842 
debug_print_params(int dbg_level,char * func,SANE_Parameters * params)1843 static void debug_print_params (int dbg_level, char* func, SANE_Parameters* params)
1844 {
1845   DBG (dbg_level, "%s: pixel_per_line: %d, lines: %d\n",
1846        func, params->pixels_per_line, params->lines);
1847 
1848   DBG (dbg_level, "%s: depth: %d, bytes_per_line: %d\n",
1849        func, params->depth, params->bytes_per_line);
1850 }
1851 
debug_print_calib_format(int dbg_level,char * func,uint8_t * result)1852 static void debug_print_calib_format (int dbg_level, char* func,
1853 				      uint8_t* result)
1854 {
1855   debug_print_raw (dbg_level + 2, "debug_print_calib_format:\n", result, 32);
1856 
1857   DBG (dbg_level, "%s: [0-1]  pixels per line: %d\n",
1858        func, get_double ( &(result[0]) ));
1859   DBG (dbg_level, "%s: [2]    bytes per channel: %d\n", func, result[2]);
1860   DBG (dbg_level, "%s: [3]    line count: %d\n", func, result[3]);
1861 
1862   DBG (dbg_level, "%s: [4]    FLAG:%s%s%s\n",
1863        func,
1864        result[4] == 1?" MUST_DO_CALIBRATION":"",
1865        result[4] == 2?" SCAN_IMAGE_DOES_CALIBRATION":"",
1866        result[4] == 3?" NEEDS_NO_CALIBRATION":"");
1867 
1868   DBG (dbg_level, "%s: [5]    Ability1:%s%s%s%s%s%s%s%s\n",
1869        func,
1870        BIT(result[5],7)?" NONE_PACKED":" PACKED",
1871        BIT(result[5],6)?" INTERPOLATED":"",
1872        BIT(result[5],5)?" SEND_REVERSED":"",
1873        BIT(result[5],4)?" PACKED_DATA":"",
1874        BIT(result[5],3)?" COLOR_CALIB":"",
1875        BIT(result[5],2)?" DARK_CALIB":"",
1876        BIT(result[5],1)?" NEEDS_WHITE_BLACK_SHADING_DATA":"",
1877        BIT(result[5],0)?" NEEDS_CALIB_TABLE_CHANNEL_BY_CHANNEL":"");
1878 
1879   DBG (dbg_level, "%s: [6]    R gain: %d\n", func, result[6]);
1880   DBG (dbg_level, "%s: [7]    G gain: %d\n", func, result[7]);
1881   DBG (dbg_level, "%s: [8]    B gain: %d\n", func, result[8]);
1882 
1883   DBG (dbg_level, "%s: [9-10] R shading target: %x\n",
1884        func, get_double ( &(result[9]) ) );
1885   DBG (dbg_level, "%s: [11-12] G shading target: %x\n",
1886        func, get_double ( &(result[11]) ) );
1887   DBG (dbg_level, "%s: [13-14] B shading target: %x\n",
1888        func, get_double ( &(result[13]) ) );
1889 
1890   DBG (dbg_level, "%s: [15-16] R dark shading target: %x\n",
1891        func, get_double ( &(result[15]) ) );
1892   DBG (dbg_level, "%s: [17-18] G dark shading target: %x\n",
1893        func, get_double ( &(result[17]) ) );
1894   DBG (dbg_level, "%s: [19-20] B dark shading target: %x\n",
1895        func, get_double ( &(result[19]) ) );
1896 
1897   DBG (dbg_level, "%s: [21]    true-gray gain: %d\n", func, result[21]);
1898   DBG (dbg_level, "%s: [22-23] true-gray shading target: %x\n",
1899        func, get_double ( &(result[22]) ) );
1900 
1901   DBG (dbg_level, "%s: [24-25] true-gray dark shading target: %x\n",
1902        func, get_double ( &(result[24]) ) );
1903 }
1904 
debug_print_accel_info(int dbg_level,char * func,uint8_t * result)1905 static void debug_print_accel_info (int dbg_level, char* func,
1906 				    uint8_t* result)
1907 {
1908   debug_print_raw (dbg_level + 2, "debug_print_accel_info:\n", result, 24);
1909 
1910   DBG (dbg_level, "%s: [0-1]   acceleration step count: %d\n",
1911        func, get_double ( &(result[0]) ));
1912   DBG (dbg_level, "%s: [2-3]   stable step count: %d\n",
1913        func, get_double ( &(result[2]) ));
1914   DBG (dbg_level, "%s: [4-7]   table units: %d\n",
1915        func, get_quad ( &(result[4]) ));
1916   DBG (dbg_level, "%s: [8-11]  base units: %d\n",
1917        func, get_quad ( &(result[8]) ));
1918   DBG (dbg_level, "%s: [12-13] start speed: %d\n",
1919        func, get_double ( &(result[12]) ));
1920   DBG (dbg_level, "%s: [14-15] target speed: %d\n",
1921        func, get_double ( &(result[14]) ));
1922   DBG (dbg_level, "%s: [16]    ability:%s%s\n",
1923        func,
1924        BIT(result[16],0)?" TWO_BYTES_PER_ELEM":" SINGLE_BYTE_PER_ELEM",
1925        BIT(result[16],1)?" LOW_HIGH_ORDER":" HIGH_LOW_ORDER");
1926   DBG (dbg_level, "%s: [17]    table count: %d\n", func, result[17]);
1927 
1928 }
1929 
debug_print_window_descriptor(int dbg_level,char * func,command_set_window_window * window)1930 static void debug_print_window_descriptor (int dbg_level, char* func,
1931 					   command_set_window_window* window)
1932 {
1933   debug_print_raw (dbg_level + 1, "window_data_header: \n",
1934 		   (uint8_t*)(&window->header),
1935 		   sizeof(window->header));
1936 
1937   debug_print_raw (dbg_level + 1, "window_descriptor: \n",
1938 		   (uint8_t*)(&window->descriptor),
1939 		   sizeof(*window) -
1940 		   sizeof(window->header));
1941 
1942   DBG (dbg_level, "%s: [0]     window_id: %d\n", func,
1943        window->descriptor.winid);
1944   DBG (dbg_level, "%s: [2-3]   x-axis res: %d\n", func,
1945        get_double (window->descriptor.xres));
1946   DBG (dbg_level, "%s: [4-5]   y-axis res: %d\n", func,
1947        get_double (window->descriptor.yres));
1948   DBG (dbg_level, "%s: [6-9]   x-axis upper left: %d\n",
1949        func, get_quad (window->descriptor.ulx));
1950   DBG (dbg_level, "%s: [10-13] y-axis upper left: %d\n",
1951        func, get_quad (window->descriptor.uly));
1952   DBG (dbg_level, "%s: [14-17] window width: %d\n", func,
1953        get_quad (window->descriptor.width));
1954   DBG (dbg_level, "%s: [18-21] window length: %d\n", func,
1955        get_quad (window->descriptor.length));
1956   DBG (dbg_level, "%s: [22]    brightness: %d\n", func,
1957        window->descriptor.brightness);
1958   DBG (dbg_level, "%s: [23]    threshold: %d\n", func,
1959        window->descriptor.threshold);
1960   DBG (dbg_level, "%s: [24]    contrast: %d\n", func,
1961        window->descriptor.contrast);
1962   DBG (dbg_level, "%s: [25]    image composition: %x\n", func,
1963        window->descriptor.image_comp);
1964   DBG (dbg_level, "%s: [26]    bits per channel: %d\n", func,
1965        window->descriptor.bpc);
1966   DBG (dbg_level, "%s: [27-28] halftone pattern: %x\n", func,
1967        get_double (window->descriptor.halftone));
1968   DBG (dbg_level, "%s: [29]    padding_and_bitset: %x\n", func,
1969        window->descriptor.padding_and_bitset);
1970   DBG (dbg_level, "%s: [30-31] bit ordering: %x\n", func,
1971        get_double (window->descriptor.bitordering));
1972   DBG (dbg_level, "%s: [32]    compression type: %x\n", func,
1973        window->descriptor.compr_type);
1974   DBG (dbg_level, "%s: [33]    compression argument: %x\n", func,
1975        window->descriptor.compr_arg);
1976   DBG (dbg_level, "%s: [34-35] paper length: %x\n", func,
1977        get_double (window->descriptor.paper_length) );
1978   DBG (dbg_level, "%s: [40]    vendor id: %x\n", func,
1979        window->descriptor.vendor_specific);
1980   DBG (dbg_level, "%s: [41]    param length: %d\n", func,
1981        window->descriptor.paralen);
1982   DBG (dbg_level, "%s: [42]    bitset1: %x\n", func,
1983        window->avision.bitset1);
1984   DBG (dbg_level, "%s: [43]    highlight: %d\n", func,
1985        window->avision.highlight);
1986   DBG (dbg_level, "%s: [44]    shadow: %d\n", func,
1987        window->avision.shadow);
1988   DBG (dbg_level, "%s: [45-46] line-width: %d\n", func,
1989        get_double (window->avision.line_width));
1990   DBG (dbg_level, "%s: [47-48] line-count: %d\n", func,
1991        get_double (window->avision.line_count));
1992   DBG (dbg_level, "%s: [49]    bitset2: %x\n", func,
1993        window->avision.type.normal.bitset2);
1994   DBG (dbg_level, "%s: [50]    ir exposure time: %x\n",
1995        func, window->avision.type.normal.ir_exposure_time);
1996 
1997   DBG (dbg_level, "%s: [51-52] r exposure: %x\n", func,
1998        get_double (window->avision.type.normal.r_exposure_time));
1999   DBG (dbg_level, "%s: [53-54] g exposure: %x\n", func,
2000        get_double (window->avision.type.normal.g_exposure_time));
2001   DBG (dbg_level, "%s: [55-56] b exposure: %x\n", func,
2002        get_double (window->avision.type.normal.b_exposure_time));
2003 
2004   DBG (dbg_level, "%s: [57]    bitset3: %x\n", func,
2005        window->avision.type.normal.bitset3);
2006   DBG (dbg_level, "%s: [58]    auto focus: %d\n", func,
2007        window->avision.type.normal.auto_focus);
2008   DBG (dbg_level, "%s: [59]    line-width (MSB): %d\n",
2009        func, window->avision.type.normal.line_width_msb);
2010   DBG (dbg_level, "%s: [60]    line-count (MSB): %d\n",
2011        func, window->avision.type.normal.line_count_msb);
2012   DBG (dbg_level, "%s: [61]    background lines: %d\n",
2013        func, window->avision.type.normal.background_lines);
2014 }
2015 
write_pnm_header(FILE * f,color_mode m,int depth,int width,int height)2016 static int write_pnm_header (FILE* f, color_mode m, int depth, int width, int height)
2017 {
2018   int maxval = (1 << depth) - 1;
2019   const char* hdr_str = NULL;
2020   /* construct PNM header */
2021 
2022   switch (m) {
2023   case AV_THRESHOLDED:
2024   case AV_DITHERED:
2025     hdr_str = "P4\n%d %d\n";
2026     break;
2027   case AV_GRAYSCALE:
2028   case AV_GRAYSCALE12:
2029   case AV_GRAYSCALE16:
2030     hdr_str = "P5\n%d %d\n%d\n";
2031     break;
2032   case AV_TRUECOLOR:
2033   case AV_TRUECOLOR12:
2034   case AV_TRUECOLOR16:
2035     hdr_str = "P6\n%d %d\n%d\n";
2036     break;
2037   case  AV_COLOR_MODE_LAST:
2038     ; /* silence compiler warning */
2039   }
2040 
2041   return fprintf (f, hdr_str, width, height, maxval);
2042 }
2043 
2044 static SANE_Status
sense_handler(int fd,u_char * sense,void * arg)2045 sense_handler (int fd, u_char* sense, void* arg)
2046 {
2047   SANE_Status status = SANE_STATUS_IO_ERROR; /* default case */
2048 
2049   char* text;
2050   char textbuf[64];
2051 
2052   uint8_t error_code = sense[0] & 0x7f;
2053   uint8_t sense_key = sense[2] & 0xf;
2054   uint8_t additional_sense = sense[7];
2055 
2056   fd = fd; /* silence gcc */
2057   arg = arg; /* silence gcc */
2058 
2059   DBG (3, "sense_handler:\n");
2060 
2061   switch (error_code)
2062     {
2063     case 0x70:
2064       text = "standard sense";
2065       break;
2066     case 0x7f:
2067       text = "Avision-specific sense";
2068       break;
2069     default:
2070       text = "unknown sense";
2071     }
2072 
2073   debug_print_raw (1, "sense_handler: data:\n", sense, 8 + additional_sense);
2074 
2075   /* request valid? */
2076   if (! (sense[0] & (1<<7))) {
2077     DBG (1, "sense_handler: sense not valid ...\n");
2078     return status;
2079   }
2080 
2081   switch (sense_key)
2082     {
2083     case 0x00:
2084       status = SANE_STATUS_GOOD;
2085       text = "ok ?!?";
2086       break;
2087     case 0x02:
2088       text = "NOT READY";
2089       break;
2090     case 0x03:
2091       text = "MEDIUM ERROR (mostly ADF)";
2092       status = SANE_STATUS_JAMMED;
2093       break;
2094     case 0x04:
2095       text = "HARDWARE ERROR";
2096       break;
2097     case 0x05:
2098       text = "ILLEGAL REQUEST";
2099       break;
2100     case 0x06:
2101       text = "UNIT ATTENTION";
2102       break;
2103     case 0x09:
2104       text = "VENDOR SPECIFIC";
2105       break;
2106     case 0x0b:
2107       text = "ABORTED COMMAND";
2108       status = SANE_STATUS_CANCELLED; /* AV610C2 cancel button */
2109       break;
2110     default:
2111       sprintf (textbuf, "got unknown sense code 0x%02x", (int)sense_key);
2112       text = textbuf;
2113     }
2114 
2115   DBG (1, "sense_handler: sense code: %s\n", text);
2116 
2117   if (sense[2] & (1<<6))
2118     DBG (1, "sense_handler: end of scan\n");
2119   else
2120     DBG (1, "sense_handler: scan has not yet been completed\n");
2121 
2122   if (sense[2] & (1<<5))
2123     DBG (1, "sense_handler: incorrect logical length\n");
2124   else
2125     DBG (1, "sense_handler: correct logical length\n");
2126 
2127   {
2128     uint8_t asc = sense[12];
2129     uint8_t ascq = sense[13];
2130 
2131 #define ADDITIONAL_SENSE(asc,ascq,txt)			\
2132     case ( (asc << 8) + ascq): text = txt; break
2133 
2134     switch ( (asc << 8) + ascq )
2135       {
2136 	/* normal */
2137 	ADDITIONAL_SENSE (0x00,0x00, "No additional sense information");
2138 	ADDITIONAL_SENSE (0x00,0x06, "I/O process terminated");
2139 	ADDITIONAL_SENSE (0x15,0x01, "Mechanical positioning error");
2140 
2141 	ADDITIONAL_SENSE (0x15,0x02, "Flatbed Home Sensor Error (OKI only");
2142 	ADDITIONAL_SENSE (0x15,0x03, "ADF Home Sensor Error (OKI only)");
2143 	ADDITIONAL_SENSE (0x15,0x04, "Lock Error (OKI only)");
2144 
2145 	ADDITIONAL_SENSE (0x1a,0x00, "parameter list length error");
2146 
2147 	ADDITIONAL_SENSE (0x20,0x00, "Invalid command");
2148 	ADDITIONAL_SENSE (0x24,0x00, "Invalid field in CDB");
2149 	ADDITIONAL_SENSE (0x25,0x00, "Logical unit not supported");
2150 	ADDITIONAL_SENSE (0x26,0x00, "Invalid field in parameter list");
2151 	ADDITIONAL_SENSE (0x26,0x01, "parameter not supported");
2152 	ADDITIONAL_SENSE (0x26,0x02, "parameter value invalid");
2153 	ADDITIONAL_SENSE (0x29,0x00, "Power-on, reset or bus device reset occurred");
2154 	ADDITIONAL_SENSE (0x2c,0x02, "Invalid combination of window specified");
2155 	ADDITIONAL_SENSE (0x2f,0x00, "Command cleared by another initiator");
2156 
2157 	ADDITIONAL_SENSE (0x3D,0x00, "Invalid Bit in Identify Message");
2158 
2159 	ADDITIONAL_SENSE (0x43,0x00, "Message error");
2160 	ADDITIONAL_SENSE (0x44,0x00, "Internal target failure");
2161 	ADDITIONAL_SENSE (0x44,0x01, "Flatbed DRAM Error(OKI only)");
2162 	ADDITIONAL_SENSE (0x44,0x02, "ADF DRAM Error(OKI only)");
2163 	ADDITIONAL_SENSE (0x44,0x03, "Write NVRAM Error");
2164 	ADDITIONAL_SENSE (0x47,0x00, "SCSI parity error");
2165 	ADDITIONAL_SENSE (0x49,0x00, "Invalid message error");
2166 
2167 	ADDITIONAL_SENSE (0x60,0x00, "Lamp failure");
2168 	ADDITIONAL_SENSE (0x60,0x01, "Flatbed Lamp error (Oki only)");
2169 	ADDITIONAL_SENSE (0x60,0x02, "ADF lamp error (Oki only)");
2170 	ADDITIONAL_SENSE (0x62,0x00, "Scan head positioning error");
2171 
2172 	ADDITIONAL_SENSE (0x80,0x01, "ADF paper jam"; status = SANE_STATUS_JAMMED);
2173 	ADDITIONAL_SENSE (0x80,0x02, "ADF cover open"; status = SANE_STATUS_COVER_OPEN);
2174 	ADDITIONAL_SENSE (0x80,0x03, "ADF chute empty"; status = SANE_STATUS_NO_DOCS);
2175 	ADDITIONAL_SENSE (0x80,0x04, "ADF paper end"; status = SANE_STATUS_EOF);
2176 	ADDITIONAL_SENSE (0x80,0x05, "Multi-feed (AV220,Kodak)");
2177 	ADDITIONAL_SENSE (0x80,0x06, "ADF prefeeding (OKI only)");
2178 	ADDITIONAL_SENSE (0x80,0x07, "Flatbed cover open (OKI only)"; status = SANE_STATUS_COVER_OPEN);
2179 	ADDITIONAL_SENSE (0x80,0x08, "FW module doesn't match with scanner");
2180         ADDITIONAL_SENSE (0x80,0x09, "Papers fed from multiple trays (DM272)");
2181         ADDITIONAL_SENSE (0x80,0x0A, "ADF Paper Start");
2182         ADDITIONAL_SENSE (0x80,0x0B, "Multiple ADF paper End and Start");
2183         ADDITIONAL_SENSE (0x80,0x0C, "Multiple ADF paper End");
2184 
2185         /* film scanner */
2186 	ADDITIONAL_SENSE (0x81,0x00, "ADF/MFP front door open"; status = SANE_STATUS_COVER_OPEN);
2187 	ADDITIONAL_SENSE (0x81,0x01, "ADF holder cartridge open"; status = SANE_STATUS_COVER_OPEN);
2188 	ADDITIONAL_SENSE (0x81,0x02, "ADF no film inside"; status = SANE_STATUS_NO_DOCS);
2189 	ADDITIONAL_SENSE (0x81,0x03, "ADF initial load fail");
2190 	ADDITIONAL_SENSE (0x81,0x04, "ADF film end"; status = SANE_STATUS_NO_DOCS);
2191 	ADDITIONAL_SENSE (0x81,0x05, "ADF forward feed error");
2192 	ADDITIONAL_SENSE (0x81,0x06, "ADF rewind error");
2193 	ADDITIONAL_SENSE (0x81,0x07, "ADF set unload");
2194 	ADDITIONAL_SENSE (0x81,0x08, "ADF adapter error");
2195 
2196 	ADDITIONAL_SENSE (0xA0,0x01, "Filter Positioning Error");
2197 
2198 	ADDITIONAL_SENSE (0x90,0x00, "Scanner busy (FW busy)");
2199 
2200       default:
2201 	sprintf (textbuf, "Unknown sense code asc: 0x%02x, ascq: 0x%02x",
2202 		 (int)asc, (int)ascq);
2203 	text = textbuf;
2204       }
2205 
2206 #undef ADDITIONAL_SENSE
2207 
2208     DBG (1, "sense_handler: sense code: %s\n", text);
2209 
2210     /* sense code specific for invalid request
2211      * it is possible to get a detailed error location here ;-)*/
2212     if (sense_key == 0x05) {
2213       if (sense[15] & (1<<7) )
2214 	{
2215 	  if (sense[15] & (1<<6) )
2216 	    DBG (1, "sense_handler: error in command parameter\n");
2217 	  else
2218 	    DBG (1, "sense_handler: error in data parameter\n");
2219 
2220 	  DBG (1, "sense_handler: error in parameter byte: %d, %x\n",
2221 	       get_double(&(sense[16])),  get_double(&(sense[16])));
2222 
2223 	  /* bit pointer valid ?*/
2224 	  if (sense[15] & (1<<3) )
2225 	    DBG (1, "sense_handler: error in command parameter\n");
2226 	  else
2227 	    DBG (1, "sense_handler: bit pointer invalid\n");
2228 	}
2229     }
2230   }
2231 
2232   return status;
2233 }
2234 
2235 /*
2236  * Avision scsi/usb multiplexers - to keep the code clean:
2237  */
2238 
2239 static SANE_Status
avision_usb_status(Avision_Connection * av_con,int retry,int timeout)2240 avision_usb_status (Avision_Connection* av_con, int retry, int timeout)
2241 {
2242   SANE_Status status = 0;
2243   uint8_t usb_status[1] = {0};
2244   size_t count = 0;
2245   int t_retry = retry;
2246 
2247 #define valid_status(status,a) (status == SANE_STATUS_GOOD ? a : 0)
2248 
2249   DBG (4, "avision_usb_status: timeout %d, %d retries\n", timeout, retry);
2250 #ifndef HAVE_SANEI_USB_SET_TIMEOUT
2251 #error "You must update include/sane/sanei_usb.h and sanei/sanei_usb.c accordingly!"
2252 #endif
2253   sanei_usb_set_timeout (timeout);
2254 
2255   /* 1st try bulk transfers - they are more lightweight ... */
2256   for (;
2257        count == 0 &&
2258        (av_con->usb_status == AVISION_USB_BULK_STATUS ||
2259 	av_con->usb_status == AVISION_USB_UNTESTED_STATUS) &&
2260        retry > 0;
2261        --retry)
2262     {
2263       count = sizeof (usb_status);
2264 
2265       DBG (5, "==> (bulk read) going down ...\n");
2266       status = sanei_usb_read_bulk (av_con->usb_dn, usb_status,
2267 				    &count);
2268       DBG (5, "<== (bulk read) got: %ld, status: %d\n",
2269 	   (u_long)count, valid_status(status, usb_status[0]));
2270 
2271       if (count > 0) {
2272 	av_con->usb_status = AVISION_USB_BULK_STATUS;
2273       }
2274     }
2275 
2276   /* reset retry count ... */
2277   retry = t_retry;
2278 
2279   /* 2nd try interrupt status read - if not yet disabled */
2280   for (;
2281        count == 0 &&
2282        (av_con->usb_status == AVISION_USB_INT_STATUS ||
2283 	av_con->usb_status == AVISION_USB_UNTESTED_STATUS) &&
2284        retry > 0;
2285        --retry)
2286   {
2287     count = sizeof (usb_status);
2288 
2289     DBG (5, "==> (interrupt read) going down ...\n");
2290     status = sanei_usb_read_int (av_con->usb_dn, usb_status,
2291 				 &count);
2292     DBG (5, "<== (interrupt read) got: %ld, status: %d\n",
2293 	 (u_long)count, valid_status(status, usb_status[0]));
2294 
2295     if (count > 0)
2296       av_con->usb_status = AVISION_USB_INT_STATUS;
2297   }
2298 
2299   if (status != SANE_STATUS_GOOD)
2300     return status;
2301 
2302   if (count == 0)
2303     return SANE_STATUS_IO_ERROR;
2304 
2305   /* 0 = ok, 2 => request sense, 8 ==> busy, else error */
2306   switch (usb_status[0])
2307     {
2308     case AVISION_USB_GOOD:
2309       return SANE_STATUS_GOOD;
2310     case AVISION_USB_REQUEST_SENSE:
2311       DBG (2, "avision_usb_status: Needs to request sense!\n");
2312       return SANE_STATUS_INVAL;
2313     case AVISION_USB_BUSY:
2314       DBG (2, "avision_usb_status: Busy!\n");
2315       return SANE_STATUS_DEVICE_BUSY;
2316     default:
2317       DBG (1, "avision_usb_status: Unknown!\n");
2318       return SANE_STATUS_INVAL;
2319     }
2320 }
2321 
avision_open(const char * device_name,Avision_Connection * av_con,SANEI_SCSI_Sense_Handler sense_handler,void * sense_arg)2322 static SANE_Status avision_open (const char* device_name,
2323 				 Avision_Connection* av_con,
2324 				 SANEI_SCSI_Sense_Handler sense_handler,
2325 				 void *sense_arg)
2326 {
2327   if (av_con->connection_type == AV_SCSI) {
2328     return sanei_scsi_open (device_name, &(av_con->scsi_fd),
2329 			    sense_handler, sense_arg);
2330   }
2331   else {
2332     SANE_Status status;
2333     status = sanei_usb_open (device_name, &(av_con->usb_dn));
2334     return status;
2335   }
2336 }
2337 
avision_open_extended(const char * device_name,Avision_Connection * av_con,SANEI_SCSI_Sense_Handler sense_handler,void * sense_arg,int * buffersize)2338 static SANE_Status avision_open_extended (const char* device_name,
2339 					  Avision_Connection* av_con,
2340 					  SANEI_SCSI_Sense_Handler sense_handler,
2341 					  void *sense_arg, int *buffersize)
2342 {
2343   if (av_con->connection_type == AV_SCSI) {
2344     return sanei_scsi_open_extended (device_name, &(av_con->scsi_fd),
2345 				     sense_handler, sense_arg, buffersize);
2346   }
2347   else {
2348     SANE_Status status;
2349     status = sanei_usb_open (device_name, &(av_con->usb_dn));
2350     return status;
2351   }
2352 }
2353 
avision_close(Avision_Connection * av_con)2354 static void avision_close (Avision_Connection* av_con)
2355 {
2356   if (av_con->connection_type == AV_SCSI) {
2357     sanei_scsi_close (av_con->scsi_fd);
2358     av_con->scsi_fd = -1;
2359   }
2360   else {
2361     sanei_usb_close (av_con->usb_dn);
2362     av_con->usb_dn = -1;
2363   }
2364 }
2365 
avision_is_open(Avision_Connection * av_con)2366 static SANE_Bool avision_is_open (Avision_Connection* av_con)
2367 {
2368   if (av_con->connection_type == AV_SCSI) {
2369     return av_con->scsi_fd >= 0;
2370   }
2371   else {
2372     return av_con->usb_dn >= 0;
2373   }
2374 }
2375 
avision_cmd(Avision_Connection * av_con,const void * cmd,size_t cmd_size,const void * src,size_t src_size,void * dst,size_t * dst_size)2376 static SANE_Status avision_cmd (Avision_Connection* av_con,
2377 				const void* cmd, size_t cmd_size,
2378 				const void* src, size_t src_size,
2379 				void* dst, size_t* dst_size)
2380 {
2381   if (av_con->connection_type == AV_SCSI) {
2382     return sanei_scsi_cmd2 (av_con->scsi_fd, cmd, cmd_size,
2383 			    src, src_size, dst, dst_size);
2384   }
2385   else {
2386     SANE_Status status = SANE_STATUS_GOOD;
2387 
2388     size_t i, count, out_count;
2389     /* some commands on some devices need a rather long time to respond */
2390 #define STD_TIMEOUT 30000
2391 #define STD_STATUS_TIMEOUT 10000
2392     int retry = 4;
2393     int write_timeout = STD_TIMEOUT;
2394     int read_timeout = STD_TIMEOUT;
2395     int status_timeout = STD_STATUS_TIMEOUT;
2396 
2397     /* simply to allow nicer code below */
2398     const uint8_t* m_cmd = (const uint8_t*)cmd;
2399     const uint8_t* m_src = (const uint8_t*)src;
2400     uint8_t* m_dst = (uint8_t*)dst;
2401 
2402     /* may I vote for the possibility to use C99 ... */
2403 #define min_usb_size 10
2404 #define max_usb_size 256 * 1024 /* or 0x10000, used by AV Windows driver during background raster read, ... ? */
2405 
2406     /* 1st send command data - at least 10 Bytes for USB scanners */
2407     uint8_t enlarged_cmd [min_usb_size];
2408     if (cmd_size < min_usb_size) {
2409       DBG (1, "filling command to have a length of 10, was: %lu\n", (u_long) cmd_size);
2410       memcpy (enlarged_cmd, m_cmd, cmd_size);
2411       memset (enlarged_cmd + cmd_size, 0, min_usb_size - cmd_size);
2412       m_cmd = enlarged_cmd;
2413       cmd_size = min_usb_size;
2414     }
2415 
2416     /* per command class timeout tweaks */
2417     switch (m_cmd[0]) {
2418       case AVISION_SCSI_INQUIRY:
2419 	read_timeout = 1000; /* quickly timeout on initial detection */
2420 	status_timeout = 1000;
2421         break;
2422       case AVISION_SCSI_TEST_UNIT_READY:
2423         read_timeout = 15000; /* quickly timeout on initial detection */
2424 	status_timeout = 15000;
2425         break;
2426     }
2427 
2428     DBG (7, "Timeouts: write: %d, read: %d, status: %d\n",
2429          write_timeout, read_timeout, status_timeout);
2430 
2431 write_usb_cmd:
2432     if (--retry == 0) {
2433       DBG (1, "Max retry count reached: I/O error\n");
2434       return SANE_STATUS_IO_ERROR;
2435     }
2436 
2437     count = cmd_size;
2438 
2439     sanei_usb_set_timeout (write_timeout);
2440     DBG (8, "try to write cmd, count: %lu.\n", (u_long) count);
2441     status = sanei_usb_write_bulk (av_con->usb_dn, m_cmd, &count);
2442 
2443     DBG (8, "wrote %lu bytes\n", (u_long) count);
2444     if (status != SANE_STATUS_GOOD || count != cmd_size) {
2445       DBG (3, "=== Got error %d trying to write, wrote: %ld. ===\n",
2446            status, (long)count);
2447 
2448       if (status != SANE_STATUS_GOOD) /* == SANE_STATUS_EOF) */ {
2449 	DBG (3, "try to read status to clear the FIFO\n");
2450 	status = avision_usb_status (av_con, 1, 500);
2451 	if (status != SANE_STATUS_GOOD) {
2452 	  DBG (3, "=== Got error %d trying to read status. ===\n", status);
2453 	  return SANE_STATUS_IO_ERROR;
2454 	}
2455 	else
2456 	  goto write_usb_cmd;
2457       } else {
2458 	DBG (3, "Retrying to send command\n");
2459 	goto write_usb_cmd;
2460       }
2461 
2462       return SANE_STATUS_IO_ERROR;
2463     }
2464 
2465     /* 2nd send command data (if any) */
2466     for (i = 0; i < src_size; ) {
2467 
2468       count = src_size - i;
2469       /* if (count > max_usb_size)
2470   	   count = max_usb_size; */
2471 
2472       DBG (8, "try to write src, count: %lu.\n", (u_long) count);
2473       sanei_usb_set_timeout (write_timeout);
2474       status = sanei_usb_write_bulk (av_con->usb_dn, &(m_src[i]), &count);
2475 
2476       DBG (8, "wrote %lu bytes\n", (u_long) count);
2477       if (status == SANE_STATUS_GOOD) {
2478 	i += count;
2479       }
2480       else {
2481 	goto write_usb_cmd;
2482       }
2483     }
2484 
2485     /* 3rd: read the resulting data (payload) (if any) */
2486     if (status == SANE_STATUS_GOOD && dst != NULL && *dst_size > 0) {
2487       out_count = 0;
2488       sanei_usb_set_timeout (read_timeout);
2489       while (out_count < *dst_size) {
2490 	count = (*dst_size - out_count);
2491 
2492 	DBG (8, "try to read %lu bytes\n", (u_long) count);
2493         status = sanei_usb_read_bulk(av_con->usb_dn, &(m_dst[out_count]),
2494 				     &count);
2495 	DBG (8, "read %lu bytes\n", (u_long) count);
2496 
2497 	if (count == 1 && (*dst_size - out_count > 1)) {
2498 	  DBG (1, "Got 1 byte - status? (%d) Resending.\n", m_dst[out_count]);
2499 	  goto write_usb_cmd;
2500         }
2501 	else if (count > 0) {
2502           out_count += count;
2503 	}
2504 	else {
2505 	  DBG (1, "No data arrived.\n");
2506 	  goto write_usb_cmd;
2507 	}
2508       }
2509     }
2510 
2511     /* last: read the device status via a pseudo interrupt transfer
2512      * this is needed - otherwise the scanner will hang ... */
2513     sanei_usb_set_timeout (status_timeout);
2514     status = avision_usb_status (av_con, /*retry*/ 1, status_timeout);
2515     /* next i/o hardening attempt - and yes this gets ugly ... */
2516     if (status != SANE_STATUS_GOOD && status != SANE_STATUS_INVAL)
2517       goto write_usb_cmd;
2518 
2519     if (status == SANE_STATUS_INVAL) {
2520       struct {
2521 	command_header header;
2522 	uint8_t pad[4];
2523       } sense_cmd;
2524 
2525       uint8_t sense_buffer[22];
2526 
2527       DBG (3, "Error during status read!\n");
2528       DBG (3, "=== Try to request sense ===\n");
2529 
2530       /* we can not call avision_cmd recursively - we might ending in
2531 	 an endless recursion requesting sense for failing request
2532 	 sense transfers ...*/
2533 
2534       memset (&sense_cmd, 0, sizeof (sense_cmd) );
2535       memset (&sense_buffer, 0, sizeof (sense_buffer) );
2536       sense_cmd.header.opc = AVISION_SCSI_REQUEST_SENSE;
2537       sense_cmd.header.len = sizeof (sense_buffer);
2538 
2539       count = sizeof(sense_cmd);
2540 
2541       DBG (8, "try to write %lu bytes\n", (u_long) count);
2542       sanei_usb_set_timeout (write_timeout);
2543       status = sanei_usb_write_bulk (av_con->usb_dn,
2544 				     (uint8_t*) &sense_cmd, &count);
2545       DBG (8, "wrote %lu bytes\n", (u_long) count);
2546 
2547       if (status != SANE_STATUS_GOOD) {
2548 	DBG (3, "=== Got error %d trying to request sense! ===\n", status);
2549       }
2550       else {
2551 	count = sizeof (sense_buffer);
2552 
2553 	DBG (8, "try to read %lu bytes sense data\n", (u_long) count);
2554 	sanei_usb_set_timeout (read_timeout);
2555 	status = sanei_usb_read_bulk(av_con->usb_dn, sense_buffer, &count);
2556 	DBG (8, "read %lu bytes sense data\n", (u_long) count);
2557 
2558 	/* we need to read out the status from the scanner i/o buffer */
2559 	status = avision_usb_status (av_con, 1, status_timeout);
2560 
2561 	/* some scanner return NEED_SENSE even after reading it */
2562 	if (status != SANE_STATUS_GOOD && status != SANE_STATUS_INVAL)
2563 	  DBG (3, "=== Got error %d trying to read sense! ===\n", status);
2564 	else {
2565 	  /* read complete -> call our sense handler */
2566 	  status = sense_handler (-1, sense_buffer, 0);
2567 	}
2568       } /* end read sense data */
2569     } /* end request sense */
2570     return status;
2571   } /* end cmd usb */
2572 }
2573 
2574 /* A bubble sort for the calibration. It only sorts the first third
2575  * and returns an average of the top 2/3 values. The input data is
2576  * 16bit big endian and the count is the count of the words - not
2577  * bytes! */
2578 
2579 static uint16_t
bubble_sort(uint8_t * sort_data,size_t count)2580 bubble_sort (uint8_t* sort_data, size_t count)
2581 {
2582   size_t i, j, limit, k;
2583   double sum = 0.0;
2584 
2585   limit = count / 3;
2586 
2587   for (i = 0; i < limit; ++i)
2588     {
2589       uint16_t ti = 0;
2590       uint16_t tj = 0;
2591 
2592       for (j = (i + 1); j < count; ++j)
2593 	{
2594 	  ti = get_double ((sort_data + i*2));
2595 	  tj = get_double ((sort_data + j*2));
2596 
2597 	  if (ti > tj) {
2598 	    set_double ((sort_data + i*2), tj);
2599 	    set_double ((sort_data + j*2), ti);
2600 	  }
2601 	}
2602     }
2603 
2604   for (k = 0, i = limit; i < count; ++i) {
2605     sum += get_double ((sort_data + i*2));
2606     ++ k;
2607   }
2608 
2609   /* DBG (7, "bubble_sort: %d values for average\n", k); */
2610 
2611   if (k > 0) /* if avg to compute */
2612     return (uint16_t) (sum / k);
2613   else
2614     return (uint16_t) (sum); /* always zero? */
2615 }
2616 
2617 static SANE_Status
add_color_mode(Avision_Device * dev,color_mode mode,SANE_String name)2618 add_color_mode (Avision_Device* dev, color_mode mode, SANE_String name)
2619 {
2620   int i;
2621   DBG (3, "add_color_mode: %d %s\n", mode, name);
2622 
2623   for (i = 0; i < AV_COLOR_MODE_LAST; ++i)
2624     {
2625       if (dev->color_list [i] == 0) {
2626 	dev->color_list [i] = strdup (name);
2627 	dev->color_list_num [i] = mode;
2628 	return SANE_STATUS_GOOD;
2629       } else if (strcmp (dev->color_list [i], name) == 0) {
2630 	/* already in list */
2631 	return SANE_STATUS_GOOD;
2632       }
2633     }
2634 
2635   DBG (3, "add_color_mode: failed\n");
2636   return SANE_STATUS_NO_MEM;
2637 }
2638 
2639 static int
last_color_mode(Avision_Device * dev)2640 last_color_mode (Avision_Device* dev)
2641 {
2642   int i = 1;
2643 
2644   while (dev->color_list [i] != 0 && i < AV_COLOR_MODE_LAST)
2645     ++i;
2646 
2647   /* we are off by one */
2648   --i;
2649 
2650   return i;
2651 }
2652 
2653 static color_mode
match_color_mode(Avision_Device * dev,SANE_String name)2654 match_color_mode (Avision_Device* dev, SANE_String name)
2655 {
2656   int i;
2657   DBG (3, "match_color_mode:\n");
2658 
2659   for (i = 0; i < AV_COLOR_MODE_LAST; ++i)
2660     {
2661       if (dev->color_list [i] != 0 && strcmp (dev->color_list [i], name) == 0) {
2662 	DBG (3, "match_color_mode: found at %d mode: %d\n",
2663 	     i, dev->color_list_num [i]);
2664 	return dev->color_list_num [i];
2665       }
2666     }
2667 
2668   DBG (3, "match_color_mode: source mode invalid\n");
2669   return AV_GRAYSCALE;
2670 }
2671 
2672 static SANE_Bool
color_mode_is_shaded(color_mode mode)2673 color_mode_is_shaded (color_mode mode)
2674 {
2675   return mode >= AV_GRAYSCALE;
2676 }
2677 
2678 static SANE_Bool
color_mode_is_color(color_mode mode)2679 color_mode_is_color (color_mode mode)
2680 {
2681   return mode >= AV_TRUECOLOR;
2682 }
2683 
2684 static SANE_Bool
is_adf_scan(Avision_Scanner * s)2685 is_adf_scan (Avision_Scanner* s)
2686 {
2687   return s->hw->scanner_type == AV_SHEETFEED || (s->hw->scanner_type == AV_FLATBED && s->source_mode_dim == AV_ADF_DIM);
2688 
2689 }
2690 
2691 static SANE_Status
add_source_mode(Avision_Device * dev,source_mode mode,SANE_String name)2692 add_source_mode (Avision_Device* dev, source_mode mode, SANE_String name)
2693 {
2694   int i;
2695 
2696   for (i = 0; i < AV_SOURCE_MODE_LAST; ++i)
2697     {
2698       if (dev->source_list [i] == 0) {
2699         dev->source_list [i] = strdup (name);
2700         dev->source_list_num [i] = mode;
2701         return SANE_STATUS_GOOD;
2702       } else if (strcmp (dev->source_list [i], name) == 0) {
2703 	/* already in list */
2704 	return SANE_STATUS_GOOD;
2705       }
2706     }
2707 
2708   return SANE_STATUS_NO_MEM;
2709 }
2710 
2711 static source_mode
match_source_mode(Avision_Device * dev,SANE_String name)2712 match_source_mode (Avision_Device* dev, SANE_String name)
2713 {
2714   int i;
2715 
2716   DBG (3, "match_source_mode: \"%s\"\n", name);
2717 
2718   for (i = 0; i < AV_SOURCE_MODE_LAST; ++i)
2719     {
2720       if (dev->source_list [i] != 0 && strcmp (dev->source_list [i], name) == 0) {
2721 	DBG (3, "match_source_mode: found at %d mode: %d\n",
2722 	     i, dev->source_list_num [i]);
2723 	return dev->source_list_num [i];
2724       }
2725     }
2726 
2727   DBG (3, "match_source_mode: source mode invalid\n");
2728   return AV_NORMAL;
2729 }
2730 
2731 static source_mode_dim
match_source_mode_dim(source_mode sm)2732 match_source_mode_dim (source_mode sm)
2733 {
2734   DBG (3, "match_source_mode_dim: %d\n", sm);
2735 
2736   switch (sm) {
2737   case AV_NORMAL:
2738     return AV_NORMAL_DIM;
2739   case AV_TRANSPARENT:
2740     return AV_TRANSPARENT_DIM;
2741   case AV_ADF:
2742   case AV_ADF_REAR:
2743   case AV_ADF_DUPLEX:
2744     return AV_ADF_DIM;
2745   default:
2746     DBG (3, "match_source_mode_dim: source mode invalid\n");
2747     return AV_NORMAL_DIM;
2748   }
2749 }
2750 
2751 static int
get_pixel_boundary(Avision_Scanner * s)2752 get_pixel_boundary (Avision_Scanner* s)
2753 {
2754   Avision_Device* dev = s->hw;
2755   int boundary;
2756 
2757   switch (s->c_mode) {
2758   case AV_TRUECOLOR:
2759   case AV_TRUECOLOR12:
2760   case AV_TRUECOLOR16:
2761     boundary = dev->inquiry_color_boundary;
2762     break;
2763   case AV_GRAYSCALE:
2764   case AV_GRAYSCALE12:
2765   case AV_GRAYSCALE16:
2766     boundary = dev->inquiry_gray_boundary;
2767     break;
2768   case AV_DITHERED:
2769     if (dev->inquiry_asic_type != AV_ASIC_C5)
2770       boundary = 32;
2771     else
2772       boundary = dev->inquiry_dithered_boundary;
2773     break;
2774   case AV_THRESHOLDED:
2775     if (dev->inquiry_asic_type != AV_ASIC_C5)
2776       boundary = 32;
2777     else
2778       boundary = dev->inquiry_thresholded_boundary;
2779     break;
2780   default:
2781     boundary = 8;
2782   }
2783 
2784   return boundary;
2785 }
2786 
2787 static SANE_Status
compute_parameters(Avision_Scanner * s)2788 compute_parameters (Avision_Scanner* s)
2789 {
2790   Avision_Device* dev = s->hw;
2791 
2792   int boundary = get_pixel_boundary (s);
2793   SANE_Bool gray_mode = color_mode_is_shaded (s->c_mode);
2794 
2795   /* interlaced duplex (higher end) or flipping paper (HP8xxx)? */
2796   s->avdimen.interlaced_duplex = s->source_mode == AV_ADF_DUPLEX &&
2797                                  dev->inquiry_duplex_interlaced;
2798 
2799   /* for infra-red we use the same code path es for interlaced
2800      duplex */
2801   if (s->val[OPT_IR].w)
2802     s->avdimen.interlaced_duplex = 1;
2803 
2804 #ifdef AVISION_ENHANCED_SANE
2805   /* quick fix for Microsoft Office Products ... */
2806   switch (s->c_mode)
2807   {
2808     case AV_THRESHOLDED:
2809     case AV_DITHERED:
2810        /* our backend already has this restriction - so this line is for
2811           documentation purposes only */
2812       boundary = boundary > 32 ? boundary : 32;
2813       break;
2814     case AV_GRAYSCALE:
2815     case AV_GRAYSCALE12:
2816     case AV_GRAYSCALE16:
2817       boundary = boundary > 4 ? boundary : 4;
2818       break;
2819     case AV_TRUECOLOR:
2820     case AV_TRUECOLOR12:
2821     case AV_TRUECOLOR16:
2822       /* 12 bytes for 24bit color - 48bit is untested w/ Office */
2823       boundary = boundary > 4 ? boundary : 4;
2824       break;
2825   }
2826 #endif
2827 
2828   DBG (3, "sane_compute_parameters:\n");
2829 
2830   DBG (3, "sane_compute_parameters: boundary %d, gray_mode: %d, \n",
2831        boundary, gray_mode);
2832 
2833   /* TODO: Implement different x/y resolutions support */
2834   s->avdimen.xres = s->val[OPT_RESOLUTION].w;
2835   s->avdimen.yres = s->val[OPT_RESOLUTION].w;
2836 
2837   /* soft scale ? */
2838   if (dev->hw->feature_type & AV_SOFT_SCALE) {
2839     /* find supported hardware resolution */
2840     const int* hw_res;
2841     const int* hw_res_list =
2842       dev->inquiry_asic_type == AV_ASIC_C5 ? hw_res_list_c5 : hw_res_list_generic;
2843 
2844     for (hw_res = hw_res_list; *hw_res && *hw_res < s->avdimen.xres; ++hw_res)
2845       /* just iterate */;
2846     s->avdimen.hw_xres = *hw_res;
2847 
2848     for (hw_res = hw_res_list; *hw_res && *hw_res < s->avdimen.yres; ++hw_res)
2849       /* just iterate */;
2850     s->avdimen.hw_yres = *hw_res;
2851 
2852     DBG (3, "sane_compute_parameters: soft scale, hw res: %dx%d\n",
2853 	 s->avdimen.hw_xres,
2854 	 s->avdimen.hw_yres);
2855 
2856     if (!s->avdimen.hw_xres || ! s->avdimen.hw_yres) {
2857       DBG (1, "sane_compute_parameters: no matching HW res for: %dx%d\n",
2858 	   s->avdimen.xres,
2859 	   s->avdimen.yres);
2860       return SANE_STATUS_INVAL;
2861     }
2862   }
2863   else {
2864     s->avdimen.hw_xres = s->val[OPT_RESOLUTION].w;
2865     s->avdimen.hw_yres = s->val[OPT_RESOLUTION].w;
2866   }
2867 
2868   DBG (3, "sane_compute_parameters: tlx: %f, tly: %f, brx: %f, bry: %f\n",
2869        SANE_UNFIX (s->val[OPT_TL_X].w), SANE_UNFIX (s->val[OPT_TL_Y].w),
2870        SANE_UNFIX (s->val[OPT_BR_X].w), SANE_UNFIX (s->val[OPT_BR_Y].w));
2871 
2872   /* window parameter in pixel */
2873   s->avdimen.tlx = s->avdimen.hw_xres * SANE_UNFIX (s->val[OPT_TL_X].w)
2874     / MM_PER_INCH;
2875   s->avdimen.tly = s->avdimen.hw_yres * SANE_UNFIX (s->val[OPT_TL_Y].w)
2876     / MM_PER_INCH;
2877   s->avdimen.brx = s->avdimen.hw_xres * SANE_UNFIX (s->val[OPT_BR_X].w)
2878     / MM_PER_INCH;
2879   s->avdimen.bry = s->avdimen.hw_yres * SANE_UNFIX (s->val[OPT_BR_Y].w)
2880     / MM_PER_INCH;
2881 
2882   /* line difference */
2883   if (color_mode_is_color (s->c_mode) &&
2884       dev->inquiry_needs_software_colorpack &&
2885       dev->inquiry_line_difference)
2886     {
2887       s->avdimen.line_difference =
2888 	(dev->inquiry_line_difference * s->avdimen.hw_yres) / dev->inquiry_optical_res;
2889 
2890       s->avdimen.bry += 2 * s->avdimen.line_difference;
2891 
2892       /* limit bry + line_difference to real scan boundary */
2893       {
2894 	long y_max = dev->inquiry_y_ranges[s->source_mode_dim] *
2895 	  s->avdimen.hw_yres / MM_PER_INCH;
2896 	DBG (3, "sane_compute_parameters: y_max: %ld, bry: %ld, line_difference: %d\n",
2897 	     y_max, s->avdimen.bry, s->avdimen.line_difference);
2898 
2899 	if (s->avdimen.bry + 2 * s->avdimen.line_difference > y_max) {
2900 	  DBG (1, "sane_compute_parameters: bry limited!\n");
2901 	  s->avdimen.bry = y_max - 2 * s->avdimen.line_difference;
2902 	}
2903       }
2904 
2905     } /* end if needs software colorpack */
2906   else {
2907     s->avdimen.line_difference = 0;
2908   }
2909 
2910   /* add overscan */
2911   if (dev->inquiry_tune_scan_length && is_adf_scan (s)) {
2912     /* some extra effort for precise rounding ... */
2913     int overscan = (s->avdimen.hw_yres *
2914 		    (SANE_UNFIX (s->val[OPT_OVERSCAN_TOP].w) +
2915 		     SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w)) + (MM_PER_INCH - 1)
2916 		    ) / MM_PER_INCH;
2917     DBG (3, "sane_compute_parameters: overscan lines: %d\n", overscan);
2918     s->avdimen.bry += overscan;
2919   }
2920 
2921   /* ADF offset compensation
2922      Calculate offsets for skipping lines later with considering overscan
2923      which applies to both, front and rear. The difference needs to be cut
2924      off on the other side. */
2925   if (dev->adf_offset_compensation && s->avdimen.interlaced_duplex) {
2926     /* ADF Duplex scan */
2927 
2928     struct {
2929       mm_offset front;
2930       mm_offset rear;
2931     } offsets = {{0, 0}, {0, 0}};
2932 
2933     double overscan;
2934     double bry_offset = 0;
2935 
2936     /* top */
2937     overscan = fmax(0, fmax(dev->hw->offset.duplex.front.top,
2938                             dev->hw->offset.duplex.rear.top));
2939 
2940     offsets.front.top += overscan - dev->hw->offset.duplex.front.top;
2941     offsets.rear.top  += overscan - dev->hw->offset.duplex.rear.top;
2942     bry_offset += overscan;
2943 
2944     /* bottom */
2945     overscan = fmax(0, fmax(dev->hw->offset.duplex.front.bottom,
2946                             dev->hw->offset.duplex.rear.bottom));
2947 
2948     offsets.front.bottom += overscan - dev->hw->offset.duplex.front.bottom;
2949     offsets.rear.bottom  += overscan - dev->hw->offset.duplex.rear.bottom;
2950     bry_offset += overscan;
2951 
2952     /* first page offset */
2953     if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN) {
2954       /* only applies to multi-sheet-scan */
2955 
2956       if (dev->hw->offset.first > 0) {
2957         /* move down:
2958            - add top overscan in send_tune_scan_length (effective for all pages!)
2959            - skip bottom lines at page n=0, front and rear
2960            - skip top lines at page n>0, front and rear
2961         */
2962         if (s->page == 0) {
2963           offsets.front.bottom += dev->hw->offset.first;
2964           offsets.rear.bottom  += dev->hw->offset.first;
2965         } else {
2966           offsets.front.top += dev->hw->offset.first;
2967           offsets.rear.top  += dev->hw->offset.first;
2968         }
2969 
2970       } else if (dev->hw->offset.first < 0) {
2971         /* move up:
2972            - add bottom overscan in send_tune_scan_length (effective for all pages!)
2973            - skip top lines at page n=0, front and rear
2974            - skip bottom lines at page n>0, front and rear
2975         */
2976         if (s->page == 0) {
2977           offsets.front.top += fabs(dev->hw->offset.first);
2978           offsets.rear.top  += fabs(dev->hw->offset.first);
2979         } else {
2980           offsets.front.bottom += fabs(dev->hw->offset.first);
2981           offsets.rear.bottom  += fabs(dev->hw->offset.first);
2982         }
2983 
2984       }
2985       bry_offset += fabs(dev->hw->offset.first);
2986     }
2987 
2988     /* convert to lines */
2989     s->avdimen.offset.front.top    = (int) ( offsets.front.top    * s->avdimen.yres / MM_PER_INCH );
2990     s->avdimen.offset.front.bottom = (int) ( offsets.front.bottom * s->avdimen.yres / MM_PER_INCH );
2991     s->avdimen.offset.rear.top     = (int) ( offsets.rear.top     * s->avdimen.yres / MM_PER_INCH );
2992     s->avdimen.offset.rear.bottom  = (int) ( offsets.rear.bottom  * s->avdimen.yres / MM_PER_INCH );
2993 
2994     /* add overscan to bry (hw_lines) */
2995     s->avdimen.bry += (long) ( bry_offset * s->avdimen.hw_yres / MM_PER_INCH );
2996 
2997     DBG (1, "sane_compute_parameters: front offset: top: %d!\n",
2998          s->avdimen.offset.front.top);
2999     DBG (1, "sane_compute_parameters: front offset: bottom: %d!\n",
3000          s->avdimen.offset.front.bottom);
3001     DBG (1, "sane_compute_parameters: rear offset: top: %d!\n",
3002          s->avdimen.offset.rear.top);
3003     DBG (1, "sane_compute_parameters: rear offset: bottom: %d!\n",
3004          s->avdimen.offset.rear.bottom);
3005 
3006   } else if (dev->adf_offset_compensation && s->source_mode == AV_ADF) {
3007     /* ADF front scan */
3008 
3009     mm_offset offsets = {0, 0};
3010     double bry_offset = 0;
3011 
3012     /* top */
3013     if (dev->hw->offset.front.top < 0)
3014       offsets.top += fabs(dev->hw->offset.front.top);
3015     else
3016       bry_offset += dev->hw->offset.front.top;
3017 
3018     /* bottom */
3019     if (dev->hw->offset.front.bottom < 0)
3020       offsets.bottom += fabs(dev->hw->offset.front.bottom);
3021     else
3022       bry_offset += dev->hw->offset.front.bottom;
3023 
3024     /* first page offset */
3025     if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN) {
3026       /* only applies to multi-sheet-scan */
3027 
3028       if (dev->hw->offset.first > 0) {
3029         /* move down:
3030            - add top overscan in send_tune_scan_length (effective for all pages!)
3031            - skip bottom lines at page n=0
3032            - skip top lines at page n>0
3033         */
3034         if (s->page == 0)
3035           offsets.bottom += dev->hw->offset.first;
3036         else
3037           offsets.top += dev->hw->offset.first;
3038 
3039       } else if (dev->hw->offset.first < 0) {
3040         /* move up:
3041            - add bottom overscan in send_tune_scan_length (effective for all pages!)
3042            - skip top lines at page n=0
3043            - skip bottom lines at page n>0
3044         */
3045         if (s->page == 0)
3046           offsets.top += fabs(dev->hw->offset.first);
3047         else
3048           offsets.bottom += fabs(dev->hw->offset.first);
3049 
3050       }
3051       bry_offset += fabs(dev->hw->offset.first);
3052     }
3053 
3054     /* convert to lines */
3055     s->avdimen.offset.front.top    = (int) ( offsets.top    * s->avdimen.yres / MM_PER_INCH );
3056     s->avdimen.offset.front.bottom = (int) ( offsets.bottom * s->avdimen.yres / MM_PER_INCH );
3057 
3058     /* add overscan to bry (hw_lines) */
3059     s->avdimen.bry += (long) ( bry_offset * s->avdimen.hw_yres / MM_PER_INCH );
3060 
3061     DBG (1, "sane_compute_parameters: front offset: top: %d!\n",
3062          s->avdimen.offset.front.top);
3063     DBG (1, "sane_compute_parameters: front offset: bottom: %d!\n",
3064          s->avdimen.offset.front.bottom);
3065 
3066   } else {
3067     s->avdimen.offset.front.top = 0;
3068     s->avdimen.offset.front.bottom = 0;
3069     s->avdimen.offset.rear.top = 0;
3070     s->avdimen.offset.rear.bottom = 0;
3071   }
3072 
3073   memset (&s->params, 0, sizeof (s->params));
3074 
3075   s->avdimen.hw_pixels_per_line = (s->avdimen.brx - s->avdimen.tlx);
3076   s->avdimen.hw_pixels_per_line -= s->avdimen.hw_pixels_per_line % boundary;
3077 
3078   s->avdimen.hw_lines = (s->avdimen.bry - s->avdimen.tly -
3079 			 2 * s->avdimen.line_difference);
3080 
3081   if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM)
3082     s->avdimen.hw_lines -= s->avdimen.hw_lines % dev->read_stripe_size;
3083 
3084   s->params.pixels_per_line = s->avdimen.hw_pixels_per_line * s->avdimen.xres / s->avdimen.hw_xres;
3085   s->params.lines = s->avdimen.hw_lines * s->avdimen.xres / s->avdimen.hw_xres;
3086   if (is_adf_scan (s))
3087     /* we can't know how many lines we'll see with an ADF because that depends on the paper length */
3088     s->params.lines = -1;
3089   if (s->c_mode == AV_THRESHOLDED || s->c_mode == AV_DITHERED)
3090     s->params.pixels_per_line -= s->params.pixels_per_line % 8;
3091 
3092   debug_print_avdimen (1, "sane_compute_parameters", &s->avdimen);
3093 
3094   switch (s->c_mode)
3095     {
3096     case AV_THRESHOLDED:
3097       s->params.format = SANE_FRAME_GRAY;
3098       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line / 8;
3099       s->params.bytes_per_line = s->params.pixels_per_line / 8;
3100       s->params.depth = 1;
3101       break;
3102     case AV_DITHERED:
3103       s->params.format = SANE_FRAME_GRAY;
3104       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line / 8;
3105       s->params.bytes_per_line = s->params.pixels_per_line / 8;
3106       s->params.depth = 1;
3107       break;
3108     case AV_GRAYSCALE:
3109       s->params.format = SANE_FRAME_GRAY;
3110       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line;
3111       s->params.bytes_per_line = s->params.pixels_per_line;
3112       s->params.depth = 8;
3113       break;
3114     case AV_GRAYSCALE12:
3115     case AV_GRAYSCALE16:
3116       s->params.format = SANE_FRAME_GRAY;
3117       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 2;
3118       s->params.bytes_per_line = s->params.pixels_per_line * 2;
3119       s->params.depth = 16;
3120       break;
3121     case AV_TRUECOLOR:
3122       s->params.format = SANE_FRAME_RGB;
3123       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 3;
3124       s->params.bytes_per_line = s->params.pixels_per_line * 3;
3125       s->params.depth = 8;
3126       break;
3127     case AV_TRUECOLOR12:
3128     case AV_TRUECOLOR16:
3129       s->params.format = SANE_FRAME_RGB;
3130       s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 3 * 2;
3131       s->params.bytes_per_line = s->params.pixels_per_line * 3 * 2;
3132       s->params.depth = 16;
3133       break;
3134     default:
3135       DBG (1, "Invalid mode. %d\n", s->c_mode);
3136       return SANE_STATUS_INVAL;
3137     } /* end switch */
3138 
3139   s->params.last_frame = SANE_TRUE;
3140 
3141   debug_print_params (1, "sane_compute_parameters", &s->params);
3142   return SANE_STATUS_GOOD;
3143 }
3144 
3145 static SANE_Status
inquiry(Avision_Connection av_con,uint8_t * data,size_t len)3146 inquiry (Avision_Connection av_con, uint8_t* data, size_t len)
3147 {
3148   SANE_Status status;
3149   command_header inquiry;
3150   int try = 2;
3151 
3152   DBG (3, "inquiry: length: %ld\n", (long)len);
3153 
3154   memset (&inquiry, 0, sizeof(inquiry));
3155   inquiry.opc = AVISION_SCSI_INQUIRY;
3156   inquiry.len = len;
3157 
3158   do {
3159     size_t size = inquiry.len;
3160 
3161     DBG (3, "inquiry: inquiring ...\n");
3162     status = avision_cmd (&av_con, &inquiry, sizeof (inquiry), 0, 0,
3163 			  data, &size);
3164     if (status == SANE_STATUS_GOOD && size == inquiry.len)
3165       break;
3166 
3167     DBG (1, "inquiry: inquiry failed (%s)\n", sane_strstatus (status));
3168     --try;
3169   } while (try > 0);
3170 
3171   return status;
3172 }
3173 
3174 static SANE_Status
wait_ready(Avision_Connection * av_con,int delay)3175 wait_ready (Avision_Connection* av_con, int delay)
3176 {
3177   SANE_Status status;
3178   int try;
3179 
3180   for (try = 0; try < 10; ++ try)
3181     {
3182       DBG (3, "wait_ready: sending TEST_UNIT_READY\n");
3183       status = avision_cmd (av_con, test_unit_ready, sizeof (test_unit_ready),
3184 			    0, 0, 0, 0);
3185       sleep (delay);
3186 
3187       switch (status)
3188 	{
3189 	default:
3190 	  /* Ignore errors while waiting for scanner to become ready.
3191 	     Some SCSI drivers return EIO while the scanner is
3192 	     returning to the home position.  */
3193 	  DBG (1, "wait_ready: test unit ready failed (%s)\n",
3194 	       sane_strstatus (status));
3195 	  /* fall through */
3196 	case SANE_STATUS_DEVICE_BUSY:
3197 	  break;
3198 	case SANE_STATUS_GOOD:
3199 	  return status;
3200 	}
3201     }
3202   DBG (1, "wait_ready: timed out after %d attempts\n", try);
3203   return SANE_STATUS_INVAL;
3204 }
3205 
3206 static SANE_Status
wait_4_light(Avision_Scanner * s)3207 wait_4_light (Avision_Scanner* s)
3208 {
3209   Avision_Device* dev = s->hw;
3210 
3211   /* read stuff */
3212   struct command_read rcmd;
3213   char* light_status[] =
3214     { "off", "on", "warming up", "needs warm up test",
3215       "light check error", "backlight on", "RESERVED" };
3216 
3217   SANE_Status status;
3218   uint8_t result;
3219   int try;
3220   size_t size = 1;
3221 
3222   DBG (3, "wait_4_light: getting light status.\n");
3223 
3224   memset (&rcmd, 0, sizeof (rcmd));
3225 
3226   rcmd.opc = AVISION_SCSI_READ;
3227   rcmd.datatypecode = 0xa0; /* get light status */
3228   set_double (rcmd.datatypequal, dev->data_dq);
3229   set_triple (rcmd.transferlen, size);
3230 
3231   for (try = 0; try < 90; ++ try) {
3232 
3233     if (s->cancelled) {
3234       DBG (3, "wait_4_light: cancelled\n");
3235       return SANE_STATUS_CANCELLED;
3236     }
3237 
3238     DBG (5, "wait_4_light: read bytes %lu\n", (u_long) size);
3239     status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size);
3240 
3241     if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3242       DBG (1, "wait_4_light: read failed (%s)\n", sane_strstatus (status));
3243       return status;
3244     }
3245 
3246     DBG (3, "wait_4_light: command is %d. Result is %d (%s)\n",
3247 	 status, result, light_status[(result>5)?6:result]);
3248 
3249     if (result == 1 || result == 5) {
3250       return SANE_STATUS_GOOD;
3251     }
3252     else if (dev->hw->feature_type & AV_LIGHT_CHECK_BOGUS) {
3253       DBG (3, "wait_4_light: scanner marked as returning bogus values in device-list!!\n");
3254       return SANE_STATUS_GOOD;
3255     }
3256     else {
3257       struct command_send scmd;
3258       uint8_t light_on = 1;
3259 
3260       /* turn on the light */
3261       DBG (3, "wait_4_light: setting light status.\n");
3262 
3263       memset (&scmd, 0, sizeof (scmd));
3264 
3265       scmd.opc = AVISION_SCSI_SEND;
3266       scmd.datatypecode = 0xa0; /* send light status */
3267       set_double (scmd.datatypequal, dev->data_dq);
3268       set_triple (scmd.transferlen, size);
3269 
3270       status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
3271 			    &light_on, sizeof (light_on), 0, 0);
3272 
3273       if (status != SANE_STATUS_GOOD) {
3274 	DBG (1, "wait_4_light: send failed (%s)\n", sane_strstatus (status));
3275 	return status;
3276       }
3277     }
3278     sleep (1);
3279   }
3280 
3281   DBG (1, "wait_4_light: timed out after %d attempts\n", try);
3282   return SANE_STATUS_DEVICE_BUSY;
3283 }
3284 
3285 static SANE_Status
set_power_save_time(Avision_Scanner * s,int time)3286 set_power_save_time (Avision_Scanner* s, int time)
3287 {
3288   struct {
3289     struct command_send cmd;
3290     uint8_t time[2];
3291   } scmd;
3292 
3293   Avision_Device* dev = s->hw;
3294   SANE_Status status;
3295 
3296   DBG (3, "set_power_save_time: time %d\n", time);
3297 
3298   memset (&scmd, 0, sizeof (scmd));
3299   scmd.cmd.opc = AVISION_SCSI_SEND;
3300   scmd.cmd.datatypecode = 0xA2; /* power-saving timer */
3301   set_double (scmd.cmd.datatypequal, dev->data_dq);
3302   set_triple (scmd.cmd.transferlen, sizeof (scmd.time) );
3303 
3304   set_double (scmd.time, time);
3305 
3306   status = avision_cmd (&s->av_con, &scmd.cmd, sizeof (scmd.cmd),
3307                         &scmd.time, sizeof (scmd.time), 0, 0);
3308   if (status != SANE_STATUS_GOOD)
3309     DBG (1, "set_power_save_time: send_data (%s)\n", sane_strstatus (status));
3310   return status;
3311 }
3312 
3313 static SANE_Status
get_firmware_status(Avision_Connection * av_con)3314 get_firmware_status (Avision_Connection* av_con)
3315 {
3316   /* read stuff */
3317   struct command_read rcmd;
3318   size_t size;
3319   SANE_Status status;
3320 
3321   firmware_status result;
3322 
3323   DBG (3, "get_firmware_status\n");
3324 
3325   size = sizeof (result);
3326 
3327   memset (&rcmd, 0, sizeof (rcmd));
3328   rcmd.opc = AVISION_SCSI_READ;
3329 
3330   rcmd.datatypecode = 0x90; /* firmware status */
3331   set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */
3332   set_triple (rcmd.transferlen, size);
3333 
3334   status = avision_cmd (av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size);
3335   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3336     DBG (1, "get_firmware_status: read failed (%s)\n",
3337 	 sane_strstatus (status));
3338     return (status);
3339   }
3340 
3341   debug_print_raw (6, "get_firmware_status: raw data:\n", (uint8_t*)&result, size);
3342 
3343   DBG (3, "get_firmware_status: [0]  needs firmware %x\n", result.download_firmware);
3344   DBG (3, "get_firmware_status: [1]  side edge: %d\n", get_double ( result.first_effective_pixel_flatbed ));
3345   DBG (3, "get_firmware_status: [3]  side edge: %d\n", get_double ( result.first_effective_pixel_adf_front ));
3346   DBG (3, "get_firmware_status: [5]  side edge: %d\n", get_double ( result.first_effective_pixel_adf_rear ));
3347 
3348   return SANE_STATUS_GOOD;
3349 }
3350 
3351 static SANE_Status
get_flash_ram_info(Avision_Connection * av_con)3352 get_flash_ram_info (Avision_Connection* av_con)
3353 {
3354   /* read stuff */
3355   struct command_read rcmd;
3356   size_t size;
3357   SANE_Status status;
3358   uint8_t result[40];
3359 
3360   DBG (3, "get_flash_ram_info\n");
3361 
3362   size = sizeof (result);
3363 
3364   memset (&rcmd, 0, sizeof (rcmd));
3365   rcmd.opc = AVISION_SCSI_READ;
3366 
3367   rcmd.datatypecode = 0x6a; /* flash ram information */
3368   set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */
3369   set_triple (rcmd.transferlen, size);
3370 
3371   status = avision_cmd (av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
3372   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3373     DBG (1, "get_flash_ram_info: read failed (%s)\n",
3374 	 sane_strstatus (status));
3375     return (status);
3376   }
3377 
3378   debug_print_raw (6, "get_flash_ram_info: raw data:\n", result, size);
3379 
3380   DBG (3, "get_flash_ram_info: [0]    data type %x\n", result [0]);
3381   DBG (3, "get_flash_ram_info: [1]    Ability1:%s%s%s%s%s%s%s%s\n",
3382        BIT(result[1],7)?" RESERVED_BIT7":"",
3383        BIT(result[1],6)?" RESERVED_BIT6":"",
3384        BIT(result[1],5)?" FONT(r/w)":"",
3385        BIT(result[1],4)?" FPGA(w)":"",
3386        BIT(result[1],3)?" FMDBG(r)":"",
3387        BIT(result[1],2)?" RAWLINE(r)":"",
3388        BIT(result[1],1)?" FIRMWARE(r/w)":"",
3389        BIT(result[1],0)?" CTAB(r/w)":"");
3390 
3391   DBG (3, "get_flash_ram_info: [2-5]   size CTAB: %d\n",
3392        get_quad ( &(result[2]) ) );
3393 
3394   DBG (3, "get_flash_ram_info: [6-9]   size FIRMWARE: %d\n",
3395        get_quad ( &(result[6]) ) );
3396 
3397   DBG (3, "get_flash_ram_info: [10-13] size RAWLINE: %d\n",
3398        get_quad ( &(result[10]) ) );
3399 
3400   DBG (3, "get_flash_ram_info: [14-17] size FMDBG: %d\n",
3401        get_quad ( &(result[14]) ) );
3402 
3403   DBG (3, "get_flash_ram_info: [18-21] size FPGA: %d\n",
3404        get_quad ( &(result[18]) ) );
3405 
3406   DBG (3, "get_flash_ram_info: [22-25] size FONT: %d\n",
3407        get_quad ( &(result[22]) ) );
3408 
3409   DBG (3, "get_flash_ram_info: [26-29] size RESERVED: %d\n",
3410        get_quad ( &(result[26]) ) );
3411 
3412   DBG (3, "get_flash_ram_info: [30-33] size RESERVED: %d\n",
3413        get_quad ( &(result[30]) ) );
3414 
3415   return SANE_STATUS_GOOD;
3416 }
3417 
3418 static SANE_Status
get_nvram_data(Avision_Scanner * s,nvram_data * nvram)3419 get_nvram_data (Avision_Scanner* s, nvram_data* nvram)
3420 {
3421   /* read stuff */
3422   struct command_send rcmd;
3423 
3424   size_t size;
3425   SANE_Status status;
3426 
3427   DBG (3, "get_nvram_data\n");
3428 
3429   size = sizeof (*nvram);
3430 
3431   memset (&rcmd, 0, sizeof (rcmd));
3432   memset (nvram, 0, size);
3433 
3434   rcmd.opc = AVISION_SCSI_READ;
3435 
3436   rcmd.datatypecode = 0x69; /* Read NVM RAM data */
3437   set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */
3438   set_triple (rcmd.transferlen, size);
3439 
3440   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0,
3441 			nvram, &size);
3442   if (status != SANE_STATUS_GOOD) {
3443     DBG (1, "get_nvram_data: read failed (%s)\n",
3444 	 sane_strstatus (status));
3445     return (status);
3446   }
3447 
3448   debug_print_nvram_data (5, "get_nvram_data", nvram);
3449 
3450   return SANE_STATUS_GOOD;
3451 }
3452 
3453 static SANE_Status
get_and_parse_nvram(Avision_Scanner * s,char * str,int n)3454 get_and_parse_nvram (Avision_Scanner* s, char* str, int n)
3455 {
3456   SANE_Status status;
3457   int i = 0;
3458   int x;
3459   nvram_data nvram;
3460   uint8_t inquiry_result [AVISION_INQUIRY_SIZE_V1];
3461 
3462   status = inquiry (s->av_con, inquiry_result, sizeof(inquiry_result));
3463   if (status == SANE_STATUS_GOOD) {
3464     i += snprintf (str+i, n-i, "Vendor: %.8s",
3465 		   inquiry_result+8);
3466     i += snprintf (str+i, n-i, "\nModel: %.16s",
3467 		   inquiry_result+16);
3468     i += snprintf (str+i, n-i, "\nFirmware: %.4s",
3469 		   inquiry_result+32);
3470   }
3471 
3472   if (!s->hw->inquiry_nvram_read)
3473     return SANE_STATUS_GOOD;
3474 
3475   status = get_nvram_data (s, &nvram);
3476   if (status == SANE_STATUS_GOOD)
3477     {
3478       if (nvram.serial[0])
3479 	i += snprintf (str+i, n-i, "\nSerial: %.24s",
3480 		       nvram.serial);
3481 
3482       if (nvram.born_year)
3483 	i += snprintf (str+i, n-i, "\nManufacturing date: %d-%d-%d",
3484 		       get_double(nvram.born_year),
3485 		       get_double(nvram.born_month),
3486 		       get_double(nvram.born_day));
3487       if (nvram.first_scan_year)
3488 	i += snprintf (str+i, n-i, "\nFirst scan date: %d-%d-%d",
3489 		       get_double(nvram.first_scan_year),
3490 		       get_double(nvram.first_scan_month),
3491 		       get_double(nvram.first_scan_day));
3492 
3493       x = get_quad (nvram.flatbed_scans);
3494       if (x)
3495 	i += snprintf (str+i, n-i, "\nFlatbed scans: %d", x);
3496       x = get_quad (nvram.pad_scans);
3497       if (x)
3498 	i += snprintf (str+i, n-i, "\nPad scans: %d", x);
3499       x = get_quad (nvram.adf_simplex_scans);
3500       if (x)
3501 	i += snprintf (str+i, n-i, "\nADF simplex scans: %d", x);
3502       x = get_quad (nvram.adf_duplex_scans);
3503       if (x)
3504 	i += snprintf (str+i, n-i, "\nADF duplex scans: %d", x);
3505     }
3506 
3507   return status;
3508 }
3509 
3510 static SANE_Status
get_power_save_time(Avision_Scanner * s,SANE_Word * time)3511 get_power_save_time (Avision_Scanner* s, SANE_Word* time)
3512 {
3513   SANE_Status status;
3514   nvram_data nvram;
3515 
3516   DBG (3, "get_power_save_time\n");
3517 
3518   if (!s->hw->inquiry_nvram_read)
3519     return SANE_STATUS_INVAL;
3520 
3521   status = get_nvram_data (s, &nvram);
3522 
3523   if (status != SANE_STATUS_GOOD) {
3524     DBG (1, "get_power_save_time: read nvram failed (%s)\n", sane_strstatus (status));
3525     return status;
3526   }
3527 
3528   *time = get_double (nvram.power_saving_time);
3529 
3530   return SANE_STATUS_GOOD;
3531 }
3532 
3533 #ifdef NEEDED
3534 
3535 static SANE_Status
send_nvram_data(Avision_Connection * av_con)3536 send_nvram_data (Avision_Connection* av_con)
3537 {
3538   /* read stuff */
3539   struct command_send scmd;
3540   size_t size;
3541   SANE_Status status;
3542 
3543   DBG (3, "send_nvram_data\n");
3544 
3545   size = sizeof (c7_nvram);
3546 
3547   memset (&scmd, 0, sizeof (scmd));
3548   scmd.opc = AVISION_SCSI_SEND;
3549 
3550   scmd.datatypecode = 0x85; /* nvram data */
3551   set_double (scmd.datatypequal, 0); /* dev->data_dq not available */
3552   set_triple (scmd.transferlen, size);
3553 
3554   status = avision_cmd (av_con, &scmd, sizeof (scmd), &c7_nvram, size,
3555 			0, 0);
3556   if (status != SANE_STATUS_GOOD) {
3557     DBG (1, "send_nvram_data: send failed (%s)\n",
3558 	 sane_strstatus (status));
3559     return (status);
3560   }
3561 
3562   return SANE_STATUS_GOOD;
3563 }
3564 
3565 static SANE_Status
send_flash_ram_data(Avision_Connection * av_con)3566 send_flash_ram_data (Avision_Connection* av_con)
3567 {
3568   /* read stuff */
3569   struct command_send scmd;
3570   size_t size;
3571   SANE_Status status;
3572 
3573   DBG (3, "send_flash_ram_data\n");
3574 
3575   size = sizeof (c7_flash_ram);
3576 
3577   memset (&scmd, 0, sizeof (scmd));
3578   scmd.opc = AVISION_SCSI_SEND;
3579 
3580   scmd.datatypecode = 0x86; /* flash data */
3581   set_double (scmd.datatypequal, 0);
3582   set_triple (scmd.transferlen, size);
3583 
3584   status = avision_cmd (av_con, &scmd, sizeof (scmd), &c7_flash_ram, size,
3585 			0, 0);
3586   if (status != SANE_STATUS_GOOD) {
3587     DBG (1, "send_flash_ram_data: send failed (%s)\n",
3588 	 sane_strstatus (status));
3589     return (status);
3590   }
3591 
3592   return SANE_STATUS_GOOD;
3593 }
3594 #endif
3595 
3596 
3597 static SANE_Status
adf_reset(Avision_Scanner * s)3598 adf_reset (Avision_Scanner* s)
3599 {
3600   SANE_Status status;
3601   Avision_Device* dev = s->hw;
3602   struct command_send scmd;
3603   struct command_read rcmd;
3604   uint8_t payload[4];
3605   size_t size;
3606   size_t n;
3607   int i;
3608   DBG (3, "adf_reset\n");
3609 
3610   /* loop twice */
3611   for (i=1; i >= 0; i--) {
3612     n=i;
3613     memset (&scmd, 0, sizeof (scmd));
3614     memset (&payload, 0, sizeof (payload));
3615     scmd.opc = AVISION_SCSI_SEND;
3616     scmd.datatypecode = 0xD0; /* unknown */
3617     set_double (scmd.datatypequal, 0);
3618     size = 2;
3619     set_triple (scmd.transferlen, size);
3620     payload[1] = 0x10 * i;  /* write 0x10 the first time, 0x00 the second */
3621     status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), payload, size, 0, 0);
3622     if (status != SANE_STATUS_GOOD) {
3623       DBG (1, "adf_reset: write %d failed (%s)\n", (2-i),
3624 	 sane_strstatus (status));
3625       return (status);
3626     }
3627     DBG (3, "adf_reset: write %d complete.\n", (2-i));
3628 
3629     memset (&rcmd, 0, sizeof (rcmd));
3630     memset (&payload, 0, sizeof (payload));
3631     rcmd.opc = AVISION_SCSI_READ;
3632     rcmd.datatypecode = 0x69; /* Read NVRAM data */
3633     set_double (rcmd.datatypequal, dev->data_dq);
3634     size = 4 - i; /* read 3 bytes the first time, 4 the second */
3635     set_triple (rcmd.transferlen, size);
3636     status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, payload, &size);
3637     if (status != SANE_STATUS_GOOD || size != (4-n)) {
3638       DBG (1, "adf_reset: read %zu failed (%s)\n", (4-n),
3639 	 sane_strstatus (status));
3640       return (status);
3641     }
3642     debug_print_raw (3, "adf_reset: raw data:\n", payload, size);
3643   }
3644   return SANE_STATUS_GOOD;
3645 }
3646 
3647 
3648 static SANE_Status
get_accessories_info(Avision_Scanner * s)3649 get_accessories_info (Avision_Scanner* s)
3650 {
3651   Avision_Device* dev = s->hw;
3652   int try = 3;
3653 
3654   /* read stuff */
3655   struct command_read rcmd;
3656   size_t size;
3657   SANE_Status status;
3658   uint8_t result[8];
3659 
3660   char* adf_model[] =
3661     { "Origami", "Oodles", "HP9930", "unknown" };
3662   const int adf_models = sizeof (adf_model) / sizeof(char*) - 1;
3663 
3664   DBG (3, "get_accessories_info\n");
3665 
3666   size = sizeof (result);
3667 
3668   memset (&rcmd, 0, sizeof (rcmd));
3669   rcmd.opc = AVISION_SCSI_READ;
3670 
3671   rcmd.datatypecode = 0x64; /* detect accessories */
3672   set_double (rcmd.datatypequal, dev->data_dq);
3673   set_triple (rcmd.transferlen, size);
3674 
3675   /* after resetting the ADF unit, try reprobing it again */
3676   RETRY:
3677 
3678   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
3679   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3680     DBG (1, "get_accessories_info: read failed (%s)\n",
3681          sane_strstatus (status));
3682     return (status);
3683   }
3684 
3685   debug_print_raw (6, "get_accessories_info: raw data:\n", result, size);
3686 
3687   DBG (3, "get_accessories_info: [0]  ADF: %x\n", result[0]);
3688   DBG (3, "get_accessories_info: [1]  Light Box: %x\n", result[1]);
3689 
3690   DBG (3, "get_accessories_info: [2]  ADF model: %d (%s)\n",
3691        result [2],
3692        adf_model[ (result[2] < adf_models) ? result[2] : adf_models ]);
3693 
3694   dev->inquiry_adf |= result [0];
3695 
3696   if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX)
3697   {
3698     if (result[0] == 1)
3699     {
3700       dev->inquiry_duplex = 1;
3701       dev->inquiry_duplex_interlaced = 0;
3702     } else if (result[0] == 0 && result[2] != 0 && !skip_adf) {
3703       /* Sometimes the scanner will report that there is no ADF attached, yet
3704        * an ADF model number will still be reported.  This happens on the
3705        * HP8200 series and possibly others.  In this case we need to reset the
3706        * the adf and try reading it again.  Skip this if the configuration says
3707        * to do so, so that we don't fail out the scanner as being broken and
3708        * unsupported if there isn't actually an ADF present.
3709        */
3710       DBG (3, "get_accessories_info: Found ADF model number but the ADF-present flag is not set. Trying to recover...\n");
3711       status = adf_reset (s);
3712       if (status != SANE_STATUS_GOOD) {
3713         DBG (3, "get_accessories_info: Failed to reset ADF: %s\n", sane_strstatus (status));
3714         return status;
3715       }
3716       DBG (1, "get_accessories_info: Waiting while ADF firmware resets...\n");
3717       sleep(3);
3718       status = wait_ready (&s->av_con, 1);
3719       if (status != SANE_STATUS_GOOD) {
3720         DBG (1, "get_accessories_info: wait_ready() failed: %s\n", sane_strstatus (status));
3721         return status;
3722       }
3723       if (try) {
3724         try--;
3725         goto RETRY;
3726       }
3727       DBG (1, "get_accessories_info: Maximum retries attempted, ADF unresponsive.\n");
3728       return SANE_STATUS_UNSUPPORTED;
3729     }
3730   }
3731 
3732   /* only honor a 1, some scanner without adapter set 0xff */
3733   if (result[1] == 1)
3734     dev->inquiry_light_box = 1;
3735 
3736   return SANE_STATUS_GOOD;
3737 }
3738 
3739 
3740 /* Returns a pointer to static char* strings or NULL for cancel (we do
3741    not want to start memcmp'ing for the cancel case). */
3742 static const char*
string_for_button(Avision_Scanner * s,int button)3743 string_for_button (Avision_Scanner* s, int button)
3744 {
3745   static char buffer [16];
3746   Avision_Device* dev = s->hw;
3747 
3748   /* dev->sane.model
3749      dev->inquiry_asic_type */
3750 
3751   if (dev->inquiry_buttons == 1)
3752     goto return_scan;
3753 
3754   /* simplex / duplex buttons */
3755   if (strcmp (dev->sane.vendor, "Xerox") == 0 ||
3756       strcmp (dev->sane.vendor, "Visioneer") == 0 ||
3757       strcmp (dev->sane.model, "AV121") == 0 ||
3758       strcmp (dev->sane.model, "AV122") == 0
3759       )
3760     {
3761       switch (button)
3762 	{
3763 	case 1: return "simplex";
3764 	case 2: return "duplex";
3765 	}
3766     }
3767 
3768   if (strcmp (dev->sane.model, "AV210C2") == 0 ||
3769       strcmp (dev->sane.model, "AV210D2+") == 0 ||
3770       strcmp (dev->sane.model, "AV220C2") == 0 ||
3771       strcmp (dev->sane.model, "AV610C2") == 0
3772       )
3773     {
3774       if (button == 1)
3775 	return NULL; /* cancel */
3776       else
3777 	goto return_scan;
3778     }
3779 
3780   /* those are unique, right now */
3781   if (strcmp (dev->sane.model, "AV610") == 0)
3782     {
3783       switch (button)
3784 	{
3785 	case 0: return "email";
3786 	case 1: return "copy";
3787 	case 2: return "scan";
3788 	}
3789     }
3790 
3791   /* last resort */
3792   snprintf (buffer, sizeof (buffer), "button%d", button);
3793   return buffer;
3794 
3795  return_scan:
3796   return "scan";
3797 }
3798 
3799 static SANE_Status
get_button_status(Avision_Scanner * s)3800 get_button_status (Avision_Scanner* s)
3801 {
3802   Avision_Device* dev = s->hw;
3803 
3804   /* read stuff */
3805   struct command_read rcmd;
3806   size_t size;
3807   SANE_Status status;
3808   /* was only 6 in an old SPEC - maybe we need a feature override :-( -ReneR */
3809   struct {
3810      uint8_t press_state;
3811      uint8_t buttons[5];
3812      uint8_t display; /* AV220 et.al. 7 segment LED display */
3813      uint8_t reserved[9];
3814   } result;
3815 
3816   unsigned int i;
3817 
3818   DBG (3, "get_button_status:\n");
3819 
3820   size = sizeof (result);
3821 
3822   /* AV220 et.al. */
3823   if (! (dev->hw->feature_type & AV_INT_BUTTON))
3824     {
3825       memset (&rcmd, 0, sizeof (rcmd));
3826       rcmd.opc = AVISION_SCSI_READ;
3827 
3828       rcmd.datatypecode = 0xA1; /* button status */
3829       set_double (rcmd.datatypequal, dev->data_dq);
3830       set_triple (rcmd.transferlen, size);
3831 
3832       status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0,
3833 			    (uint8_t*)&result, &size);
3834       if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3835 	DBG (1, "get_button_status: read failed (%s)\n", sane_strstatus (status));
3836 	return status;
3837       }
3838     }
3839   else
3840     {
3841       /* only try to read the first 8 bytes ...*/
3842       size = 8;
3843 
3844       /* no SCSI equivalent */
3845       /* either there was a button press and this completes quickly
3846          or there is no point waiting for a future press */
3847       sanei_usb_set_timeout (100); /* 10th of a second */
3848       DBG (5, "==> (interrupt read) going down ...\n");
3849       status = sanei_usb_read_int (s->av_con.usb_dn, (uint8_t*)&result,
3850 				   &size);
3851       DBG (5, "==> (interrupt read) got: %ld\n", (long)size);
3852 
3853       if (status != SANE_STATUS_GOOD) {
3854 	DBG (1, "get_button_status: interrupt read failed (%s)\n",
3855 	     sane_strstatus (status));
3856 	return SANE_STATUS_GOOD;
3857       }
3858 
3859       if (size < sizeof (result))
3860 	memset ((char*)result.buttons + size, 0, sizeof (result) - size);
3861 
3862       /* hack to fill in meaningful values for the AV 210 / 610 and
3863 	 under some conditions the AV 220 */
3864       if (size == 1) { /* AV 210, AV 610 */
3865 	DBG (1, "get_button_status: just one byte, filling the rest\n");
3866 
3867 	if (result.press_state > 0) {
3868 	  debug_print_raw (6, "get_button_status: raw data\n",
3869 			   (uint8_t*)&result, size);
3870 	  result.buttons[0] = result.press_state;
3871 	  result.press_state = 0x80 | 1;
3872 	  size = 2;
3873 	}
3874 	else /* nothing pressed */
3875 	  return SANE_STATUS_GOOD;
3876       }
3877       else if (size >= 8 && result.press_state == 0) { /* AV 220 */
3878 
3879 	debug_print_raw (6, "get_button_status: raw data\n",
3880 		   (uint8_t*)&result, size);
3881 
3882 	DBG (1, "get_button_status: zero buttons  - filling values ...\n");
3883 
3884 	/* simulate button press of the last button ... */
3885 	result.press_state = 0x80 | 1;
3886 	result.buttons[0] = dev->inquiry_buttons; /* 1 based */
3887       }
3888     }
3889 
3890   debug_print_raw (6, "get_button_status: raw data\n",
3891 		   (uint8_t*)&result, size);
3892 
3893   DBG (3, "get_button_status: [0]  Button status: %x\n", result.press_state);
3894   for (i = 0; i < 5; ++i)
3895     DBG (3, "get_button_status: [%d]  Button number %d: %x\n", i+1, i,
3896 	 result.buttons[i]);
3897   DBG (3, "get_button_status: [7]  Display: %d\n", result.display);
3898 
3899   {
3900     char* message_begin = s->val[OPT_MESSAGE].s;
3901     char* message_end = s->val[OPT_MESSAGE].s + s->opt[OPT_MESSAGE].size;
3902     char* message = message_begin;
3903 
3904 #define add_token(format,value) do {				     \
3905       int n = snprintf (message, message_end - message, "%s" format, \
3906                         message == message_begin ? "" : ":", value); \
3907       message += n > 0 ? n : 0;					     \
3908     } while (0)
3909 
3910     if (result.display > 0)
3911       add_token ("%d", result.display);
3912 
3913     if (result.press_state >> 7) /* AV220 et.al. bit 6 is long/short press? */
3914       {
3915 
3916 	const unsigned int buttons_pressed = result.press_state & 0x7F;
3917 	DBG (3, "get_button_status: %d button(s) pressed\n", buttons_pressed);
3918 
3919 	/* reset the hardware button status */
3920 	if (! (dev->hw->feature_type & AV_INT_BUTTON))
3921 	  {
3922 	    struct command_send scmd;
3923 	    uint8_t button_reset = 1;
3924 
3925 	    DBG (3, "get_button_status: resetting status\n");
3926 
3927 	    memset (&scmd, 0, sizeof (scmd));
3928 
3929 	    scmd.opc = AVISION_SCSI_SEND;
3930 	    scmd.datatypecode = 0xA1; /* button control */
3931 	    set_double (scmd.datatypequal, dev->data_dq);
3932 	    set_triple (scmd.transferlen, size);
3933 
3934 	    status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
3935 				  &button_reset, sizeof (button_reset), 0, 0);
3936 
3937 	    if (status != SANE_STATUS_GOOD) {
3938 	      DBG (1, "get_button_status: send failed (%s)\n",
3939 		   sane_strstatus (status));
3940 	      return status;
3941 	    }
3942 	  }
3943 
3944 	for (i = 0; i < buttons_pressed; ++i) {
3945 	  const unsigned int button = result.buttons[i] - 1; /* 1 based ... */
3946 	  DBG (3, "get_button_status: button %d pressed\n", button);
3947 	  if (button >= dev->inquiry_buttons) {
3948 	    DBG (1, "get_button_status: button %d not allocated as not indicated in inquiry\n",
3949 		 button);
3950 	  }
3951 	  else {
3952 	    const char* label = string_for_button (s, button);
3953 	    if (label)
3954 	      add_token ("%s", label);
3955 	    else
3956 	      return SANE_STATUS_CANCELLED;
3957 	  }
3958 	}
3959       }
3960     else
3961       DBG (3, "get_button_status: no button pressed\n");
3962   }
3963 
3964   return SANE_STATUS_GOOD;
3965 #undef add_token
3966 }
3967 
3968 static SANE_Status
get_frame_info(Avision_Scanner * s)3969 get_frame_info (Avision_Scanner* s)
3970 {
3971   Avision_Device* dev = s->hw;
3972 
3973   /* read stuff */
3974   struct command_read rcmd;
3975   size_t size;
3976   SANE_Status status;
3977   uint8_t result[8];
3978   size_t i;
3979 
3980   DBG (3, "get_frame_info:\n");
3981 
3982   size = sizeof (result);
3983 
3984   memset (&rcmd, 0, sizeof (rcmd));
3985   rcmd.opc = AVISION_SCSI_READ;
3986 
3987   rcmd.datatypecode = 0x87; /* film holder sense */
3988   set_double (rcmd.datatypequal, dev->data_dq);
3989   set_triple (rcmd.transferlen, size);
3990 
3991   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
3992   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3993     DBG (1, "get_frame_info: read failed (%s)\n", sane_strstatus (status));
3994     return (status);
3995   }
3996 
3997   debug_print_raw (6, "get_frame_info: raw data\n", result, size);
3998 
3999   DBG (3, "get_frame_info: [0]  Holder type: %s\n",
4000        (result[0]==1)?"APS":
4001        (result[0]==2)?"Film holder (35mm)":
4002        (result[0]==3)?"Slide holder":
4003        (result[0]==0xff)?"Empty":"unknown");
4004   DBG (3, "get_frame_info: [1]  Current frame number: %d\n", result[1]);
4005   DBG (3, "get_frame_info: [2]  Frame amount: %d\n", result[2]);
4006   DBG (3, "get_frame_info: [3]  Mode: %s\n", BIT(result[3],4)?"APS":"Not APS");
4007   DBG (3, "get_frame_info: [3]  Exposures (if APS): %s\n",
4008        ((i=(BIT(result[3],3)<<1)+BIT(result[2],2))==0)?"Unknown":
4009        (i==1)?"15":(i==2)?"25":"40");
4010   DBG (3, "get_frame_info: [3]  Film Type (if APS): %s\n",
4011        ((i=(BIT(result[1],3)<<1)+BIT(result[0],2))==0)?"Unknown":
4012        (i==1)?"B&W Negative":(i==2)?"Color slide":"Color Negative");
4013 
4014   dev->holder_type = result[0];
4015   dev->current_frame = result[1];
4016 
4017   dev->frame_range.min = 1;
4018   dev->frame_range.quant = 1;
4019 
4020   if (result[0] != 0xff)
4021     dev->frame_range.max = result[2];
4022   else
4023     dev->frame_range.max = 1;
4024 
4025   return SANE_STATUS_GOOD;
4026 }
4027 
4028 static SANE_Status
get_duplex_info(Avision_Scanner * s)4029 get_duplex_info (Avision_Scanner* s)
4030 {
4031   Avision_Device* dev = s->hw;
4032 
4033   /* read stuff */
4034   struct command_read rcmd;
4035 
4036   struct {
4037      uint8_t mode;
4038      uint8_t color_line_difference[2];
4039      uint8_t gray_line_difference[2];
4040      uint8_t lineart_line_difference[2];
4041      uint8_t image_info;
4042   } result;
4043 
4044   size_t size;
4045   SANE_Status status;
4046 
4047   DBG (3, "get_duplex_info:\n");
4048 
4049   size = sizeof (result);
4050 
4051   memset (&rcmd, 0, sizeof (rcmd));
4052   rcmd.opc = AVISION_SCSI_READ;
4053 
4054   rcmd.datatypecode = 0xB1; /* read duplex info */
4055   set_double (rcmd.datatypequal, dev->data_dq);
4056   set_triple (rcmd.transferlen, size);
4057 
4058   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0,
4059 			&result, &size);
4060   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
4061     DBG (1, "get_duplex_info: read failed (%s)\n", sane_strstatus (status));
4062     return (status);
4063   }
4064 
4065   debug_print_raw (6, "get_duplex_info: raw data\n", (uint8_t*)&result, size);
4066 
4067   DBG (3, "get_duplex_info: [0]    Mode: %s%s\n",
4068        BIT(result.mode,0)?"MERGED_PAGES":"",
4069        BIT(result.mode,1)?"2ND_PAGE_FOLLOWS":"");
4070   DBG (3, "get_duplex_info: [1-2]  Color line difference: %d\n",
4071        get_double(result.color_line_difference));
4072   DBG (3, "get_duplex_info: [3-4]  Gray line difference: %d\n",
4073        get_double(result.gray_line_difference));
4074   DBG (3, "get_duplex_info: [5-6]  Lineart line difference: %d\n",
4075        get_double(result.lineart_line_difference));
4076   /* isn't this supposed to be result.info ?!? */
4077   DBG (3, "get_duplex_info: [7]    Mode: %s%s%s%s\n",
4078        BIT(result.image_info,0)?" FLATBED_BGR":" FLATBED_RGB",
4079        BIT(result.image_info,1)?" ADF_BGR":" ADF_RGB",
4080        BIT(result.image_info,2)?" FLATBED_NEEDS_MIRROR_IMAGE":"",
4081        BIT(result.image_info,3)?" ADF_NEEDS_MIRROR_IMAGE":"");
4082 
4083   return SANE_STATUS_GOOD;
4084 }
4085 
4086 static SANE_Status
set_frame(Avision_Scanner * s,SANE_Word frame)4087 set_frame (Avision_Scanner* s, SANE_Word frame)
4088 {
4089   struct {
4090     struct command_send cmd;
4091     uint8_t data[8];
4092   } scmd;
4093 
4094   Avision_Device* dev = s->hw;
4095   SANE_Status status;
4096 
4097   DBG (3, "set_frame: request frame %d\n", frame);
4098 
4099   /* Better check the current status of the film holder, because it
4100      can be changed between scans. */
4101   status = get_frame_info (s);
4102   if (status != SANE_STATUS_GOOD)
4103     return status;
4104 
4105   /* No film holder? */
4106   if (dev->holder_type == 0xff) {
4107     DBG (1, "set_frame: No film holder!!\n");
4108     return SANE_STATUS_INVAL;
4109   }
4110 
4111   /* Requesting frame 0xff indicates eject/rewind */
4112   if (frame != 0xff && (frame < 1 || frame > dev->frame_range.max) ) {
4113     DBG (1, "set_frame: Illegal frame (%d) requested (min=1, max=%d)\n",
4114 	 frame, dev->frame_range.max);
4115     return SANE_STATUS_INVAL;
4116   }
4117 
4118   memset (&scmd, 0, sizeof (scmd));
4119   scmd.cmd.opc = AVISION_SCSI_SEND;
4120   scmd.cmd.datatypecode = 0x87; /* send film holder "sense" */
4121   set_double (scmd.cmd.datatypequal, dev->data_dq);
4122   set_triple (scmd.cmd.transferlen, sizeof (scmd.data) );
4123 
4124   scmd.data[0] = dev->holder_type;
4125   scmd.data[1] = frame;
4126 
4127   status = avision_cmd (&s->av_con, &scmd.cmd, sizeof (scmd.cmd),
4128 			&scmd.data, sizeof (scmd.data), 0, 0);
4129   if (status != SANE_STATUS_GOOD) {
4130     DBG (1, "set_frame: send_data (%s)\n", sane_strstatus (status));
4131   }
4132 
4133   return status;
4134 }
4135 
4136 static SANE_Status
attach(SANE_String_Const devname,Avision_ConnectionType con_type,Avision_Device ** devp)4137 attach (SANE_String_Const devname, Avision_ConnectionType con_type,
4138         Avision_Device** devp)
4139 {
4140   uint8_t result [AVISION_INQUIRY_SIZE_MAX];
4141   int model_num;
4142 
4143   Avision_Device* dev;
4144   SANE_Status status;
4145 
4146   Avision_Connection av_con;
4147 
4148   char mfg [9];
4149   char model [17];
4150   char rev [5];
4151 
4152   unsigned int i;
4153   char* s;
4154   SANE_Bool found;
4155 
4156   DBG (3, "attach:\n");
4157   memset (result, 0, sizeof(result));
4158 
4159   for (dev = first_dev; dev; dev = dev->next)
4160     if (strcmp (dev->sane.name, devname) == 0) {
4161       if (devp)
4162 	*devp = dev;
4163       return SANE_STATUS_GOOD;
4164     }
4165 
4166   av_con.connection_type = con_type;
4167   if (av_con.connection_type == AV_USB)
4168     av_con.usb_status = AVISION_USB_UNTESTED_STATUS;
4169 
4170   /* set known USB status type */
4171   if (attaching_hw && (attaching_hw->feature_type & AV_INT_STATUS))
4172     av_con.usb_status = AVISION_USB_INT_STATUS;
4173 
4174   DBG (3, "attach: opening %s\n", devname);
4175   status = avision_open (devname, &av_con, sense_handler, 0);
4176   if (status != SANE_STATUS_GOOD) {
4177     DBG (1, "attach: open failed (%s)\n", sane_strstatus (status));
4178     return SANE_STATUS_INVAL;
4179   }
4180 
4181   /* first: get the standard inquiry? */
4182   status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1);
4183   if (status != SANE_STATUS_GOOD) {
4184     DBG (1, "attach: 1st inquiry failed (%s)\n", sane_strstatus (status));
4185     return status;
4186   }
4187 
4188   /* copy string information - and zero terminate them c-style */
4189   memcpy (&mfg, result + 8, 8);
4190   mfg [8] = 0;
4191   memcpy (&model, result + 16, 16);
4192   model [16] = 0;
4193   memcpy (&rev, result + 32, 4);
4194   rev [4] = 0;
4195 
4196   /* shorten strings (-1 for last index
4197      -1 for last 0; >0 because one char at least) */
4198   for (i = sizeof (mfg) - 2; i > 0; i--) {
4199     if (mfg[i] == 0x20)
4200       mfg[i] = 0;
4201     else
4202       break;
4203   }
4204   for (i = sizeof (model) - 2; i > 0; i--) {
4205     if (model[i] == 0x20)
4206       model[i] = 0;
4207     else
4208       break;
4209   }
4210 
4211   DBG (1, "attach: Inquiry gives mfg=%s, model=%s, product revision=%s.\n",
4212        mfg, model, rev);
4213 
4214   model_num = 0;
4215   found = 0;
4216   /* while not at at end of list NULL terminator */
4217   while (Avision_Device_List[model_num].real_mfg != NULL ||
4218          Avision_Device_List[model_num].scsi_mfg != NULL)
4219   {
4220     int matches = 0, match_count = 0; /* count number of matches */
4221     DBG (1, "attach: Checking model: %d\n", model_num);
4222 
4223     if (Avision_Device_List[model_num].scsi_mfg) {
4224       ++match_count;
4225       if (strcmp(mfg, Avision_Device_List[model_num].scsi_mfg) == 0)
4226         ++matches;
4227     }
4228     if (Avision_Device_List[model_num].scsi_model) {
4229       ++match_count;
4230       if (strcmp(model, Avision_Device_List[model_num].scsi_model) == 0)
4231         ++matches;
4232     }
4233 
4234     /* we need 2 matches (mfg, model) for SCSI entries, or the ones available
4235        for "we know what we are looking for" USB entries */
4236     if ((attaching_hw == &(Avision_Device_List [model_num]) &&
4237          matches == match_count) ||
4238 	matches == 2)
4239     {
4240       DBG (1, "attach: Scanner matched entry: %d: \"%s\", \"%s\", 0x%.4x, 0x%.4x\n",
4241            model_num,
4242 	   Avision_Device_List[model_num].scsi_mfg,
4243 	   Avision_Device_List[model_num].scsi_model,
4244 	   Avision_Device_List[model_num].usb_vendor,
4245 	   Avision_Device_List[model_num].usb_product);
4246       found = 1;
4247       break;
4248     }
4249     ++model_num;
4250   }
4251 
4252   if (!found) {
4253     DBG (0, "attach: \"%s\" - \"%s\" not yet in whitelist!\n", mfg, model);
4254     DBG (0, "attach: You might want to report this output.\n");
4255     DBG (0, "attach: To: rene@exactcode.de (the Avision backend author)\n");
4256 
4257     status = SANE_STATUS_INVAL;
4258     goto close_scanner_and_return;
4259   }
4260 
4261   /* second: maybe ask for the firmware status and flash ram info */
4262   if (Avision_Device_List [model_num].feature_type & AV_FIRMWARE)
4263   {
4264       DBG (3, "attach: reading firmware status\n");
4265       status = get_firmware_status (&av_con);
4266       if (status != SANE_STATUS_GOOD) {
4267 	DBG (1, "attach: get firmware status failed (%s)\n",
4268 	     sane_strstatus (status));
4269 	goto close_scanner_and_return;
4270       }
4271 
4272       DBG (3, "attach: reading flash ram info\n");
4273       status = get_flash_ram_info (&av_con);
4274       if (status != SANE_STATUS_GOOD) {
4275 	DBG (1, "attach: get flash ram info failed (%s)\n",
4276 	     sane_strstatus (status));
4277 	goto close_scanner_and_return;
4278       }
4279 
4280 #ifdef FIRMWARE_DATABASE_INCLUDED
4281       /* Send new NV-RAM (firmware) data */
4282       status = send_nvram_data (&av_con);
4283       if (status != SANE_STATUS_GOOD)
4284 	goto close_scanner_and_return;
4285 #endif
4286   }
4287 
4288   /* third: get the extended Avision inquiry */
4289   status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1);
4290   if (status != SANE_STATUS_GOOD) {
4291     DBG (1, "attach: avision v1 inquiry failed (%s)\n", sane_strstatus (status));
4292     goto close_scanner_and_return;
4293   }
4294 
4295   dev = malloc (sizeof (*dev));
4296   if (!dev) {
4297     status = SANE_STATUS_NO_MEM;
4298     goto close_scanner_and_return;
4299   }
4300 
4301   memset (dev, 0, sizeof (*dev));
4302 
4303   dev->hw = &Avision_Device_List[model_num];
4304 
4305   dev->sane.name   = strdup (devname);
4306   dev->sane.vendor = dev->hw->real_mfg   ? dev->hw->real_mfg   : strdup (mfg);
4307   dev->sane.model  = dev->hw->real_model ? dev->hw->real_model : strdup (model);
4308   dev->connection.connection_type = av_con.connection_type;
4309   dev->connection.usb_status = av_con.usb_status;
4310 
4311   /* and finally Avision even extended this one later on
4312      the AV220C2 does not grok this */
4313   dev->inquiry_asic_type = (int) result[91];
4314   if (dev->inquiry_asic_type == AV_ASIC_C6)
4315     {
4316       status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V2);
4317       if (status != SANE_STATUS_GOOD) {
4318 	DBG (1, "attach: avision v2 inquiry failed (%s)\n", sane_strstatus (status));
4319 	goto close_scanner_and_return;
4320       }
4321     }
4322 
4323   debug_print_raw (6, "attach: raw data:\n", result, sizeof (result) );
4324 
4325   DBG (3, "attach: [8-15]  Vendor id.:      '%8.8s'\n", result+8);
4326   DBG (3, "attach: [16-31] Product id.:     '%16.16s'\n", result+16);
4327   DBG (3, "attach: [32-35] Product rev.:    '%4.4s'\n", result+32);
4328 
4329   i = (result[36] >> 4) & 0x7;
4330   switch (result[36] & 0x07) {
4331   case 0:
4332     s = " RGB"; break;
4333   case 1:
4334     s = " BGR"; break;
4335   default:
4336     s = " unknown (RESERVED)";
4337   }
4338   DBG (3, "attach: [36]    Bitfield:%s%s%s%s%s%s%s color plane\n",
4339        BIT(result[36],7)?" ADF":"",
4340        (i==0)?" B&W only":"",
4341        BIT(i, 1)?" 3-pass color":"",
4342        BIT(i, 2)?" 1-pass color":"",
4343        BIT(i, 2) && BIT(i, 0) ?" 1-pass color (ScanPartner only)":"",
4344        BIT(result[36],3)?" IS_NOT_FLATBED":"",
4345        s);
4346 
4347   DBG (3, "attach: [37]    Optical res.:    %d00 dpi\n", result[37]);
4348   DBG (3, "attach: [38]    Maximum res.:    %d00 dpi\n", result[38]);
4349 
4350   DBG (3, "attach: [39]    Bitfield1:%s%s%s%s%s%s\n",
4351        BIT(result[39],7)?" TRANS":"",
4352        BIT(result[39],6)?" Q_SCAN":"",
4353        BIT(result[39],5)?" EXTENDED_RES":"",
4354        BIT(result[39],4)?" SUPPORTS_CALIB":"",
4355        BIT(result[39],2)?" NEW_PROTOCOL":"",
4356        (result[39] & 0x03) == 0x03 ? " AVISION":" OEM");
4357 
4358   DBG (3, "attach: [40-41] X res. in gray:  %d dpi\n",
4359        get_double ( &(result[40]) ));
4360   DBG (3, "attach: [42-43] Y res. in gray:  %d dpi\n",
4361        get_double ( &(result[42]) ));
4362   DBG (3, "attach: [44-45] X res. in color: %d dpi\n",
4363        get_double ( &(result[44]) ));
4364   DBG (3, "attach: [46-47] Y res. in color: %d dpi\n",
4365        get_double ( &(result[46]) ));
4366   DBG (3, "attach: [48-49] USB max read:    %d\n",
4367 get_double ( &(result[48] ) ));
4368 
4369   DBG (3, "attach: [50]    ESA1:%s%s%s%s%s%s%s%s\n",
4370        BIT(result[50],7)?" LIGHT_CONTROL":"",
4371        BIT(result[50],6)?" BUTTON_CONTROL":"",
4372        BIT(result[50],5)?" NEED_SW_COLORPACK":"",
4373        BIT(result[50],4)?" SW_CALIB":"",
4374        BIT(result[50],3)?" NEED_SW_GAMMA":"",
4375        BIT(result[50],2)?" KEEPS_GAMMA":"",
4376        BIT(result[50],1)?" KEEPS_WINDOW_CMD":"",
4377        BIT(result[50],0)?" XYRES_DIFFERENT":"");
4378   DBG (3, "attach: [51]    ESA2:%s%s%s%s%s%s%s%s\n",
4379        BIT(result[51],7)?" EXPOSURE_CTRL":"",
4380        BIT(result[51],6)?" NEED_SW_TRIGGER_CAL":"",
4381        BIT(result[51],5)?" NEED_WHITE_PAPER_CALIB":"",
4382        BIT(result[51],4)?" SUPPORTS_QUALITY_SPEED_CAL":"",
4383        BIT(result[51],3)?" NEED_TRANSP_CAL":"",
4384        BIT(result[51],2)?" HAS_PUSH_BUTTON":"",
4385        BIT(result[51],1)?" NEW_CAL_METHOD_3x3_MATRIX_(NO_GAMMA_TABLE)":"",
4386        BIT(result[51],0)?" ADF_MIRRORS_IMAGE":"");
4387   DBG (3, "attach: [52]    ESA3:%s%s%s%s%s%s%s%s\n",
4388        BIT(result[52],7)?" GRAY_WHITE":"",
4389        BIT(result[52],6)?" SUPPORTS_GAIN_CONTROL":"",
4390        BIT(result[52],5)?" SUPPORTS_TET":"", /* "Text Enhanced Technology" */
4391        BIT(result[52],4)?" 3x3COL_TABLE":"",
4392        BIT(result[52],3)?" 1x3FILTER":"",
4393        BIT(result[52],2)?" INDEX_COLOR":"",
4394        BIT(result[52],1)?" POWER_SAVING_TIMER":"",
4395        BIT(result[52],0)?" NVM_DATA_REC":"");
4396 
4397   /* print some more scanner features/params */
4398   DBG (3, "attach: [53]    line difference (software color pack): %d\n", result[53]);
4399   DBG (3, "attach: [54]    color mode pixel boundary: %d\n", result[54]);
4400   DBG (3, "attach: [55]    gray mode pixel boundary: %d\n", result[55]);
4401   DBG (3, "attach: [56]    4bit gray mode pixel boundary: %d\n", result[56]);
4402   DBG (3, "attach: [57]    lineart mode pixel boundary: %d\n", result[57]);
4403   DBG (3, "attach: [58]    halftone mode pixel boundary: %d\n", result[58]);
4404   DBG (3, "attach: [59]    error-diffusion mode pixel boundary: %d\n", result[59]);
4405 
4406   DBG (3, "attach: [60]    channels per pixel:%s%s%s\n",
4407        BIT(result[60],7)?" 1":"",
4408        BIT(result[60],6)?" 3":"",
4409        (result[60] & 0x3F) != 0 ? " RESERVED":"");
4410 
4411   DBG (3, "attach: [61]    bits per channel:%s%s%s%s%s%s%s\n",
4412        BIT(result[61],7)?" 1":"",
4413        BIT(result[61],6)?" 4":"",
4414        BIT(result[61],5)?" 6":"",
4415        BIT(result[61],4)?" 8":"",
4416        BIT(result[61],3)?" 10":"",
4417        BIT(result[61],2)?" 12":"",
4418        BIT(result[61],1)?" 16":"");
4419 
4420   DBG (3, "attach: [62]    scanner type:%s%s%s%s%s%s\n",
4421        BIT(result[62],7)?" Flatbed":"",
4422        BIT(result[62],6)?" Roller (ADF)":"",
4423        BIT(result[62],5)?" Flatbed (ADF)":"",
4424        BIT(result[62],4)?" Roller":"", /* does not feed multiple pages, AV25 */
4425        BIT(result[62],3)?" Film scanner":"",
4426        BIT(result[62],2)?" Duplex":"");
4427 
4428   DBG (3, "attach: [75-76] Max shading target : %x\n",
4429        get_double ( &(result[75]) ));
4430 
4431   DBG (3, "attach: [77-78] Max X of transparency: %d dots * base_dpi\n",
4432        get_double ( &(result[77]) ));
4433   DBG (3, "attach: [79-80] Max Y of transparency: %d dots * base_dpi\n",
4434        get_double ( &(result[79]) ));
4435 
4436   DBG (3, "attach: [81-82] Max X of flatbed:      %d dots * base_dpi\n",
4437        get_double ( &(result[81]) ));
4438   DBG (3, "attach: [83-84] Max Y of flatbed:      %d dots * base_dpi\n",
4439        get_double ( &(result[83]) ));
4440 
4441   DBG (3, "attach: [85-86] Max X of ADF:          %d dots * base_dpi\n",
4442        get_double ( &(result[85]) ));
4443   DBG (3, "attach: [87-88] Max Y of ADF:          %d dots * base_dpi\n",
4444        get_double ( &(result[87]) )); /* 0xFFFF means unlimited length */
4445 
4446   DBG (3, "attach: [89-90] Res. in Ex. mode:      %d dpi\n",
4447        get_double ( &(result[89]) ));
4448 
4449   DBG (3, "attach: [91]    ASIC:     %d\n", result[91]);
4450 
4451   DBG (3, "attach: [92]    Buttons:  %d\n", result[92]);
4452 
4453   DBG (3, "attach: [93]    ESA4:%s%s%s%s%s%s%s%s\n",
4454        BIT(result[93],7)?" SUPPORTS_ACCESSORIES_DETECT":"",
4455        BIT(result[93],6)?" ADF_IS_BGR_ORDERED":"",
4456        BIT(result[93],5)?" NO_SINGLE_CHANNEL_GRAY_MODE":"",
4457        BIT(result[93],4)?" SUPPORTS_FLASH_UPDATE":"",
4458        BIT(result[93],3)?" SUPPORTS_ASIC_UPDATE":"",
4459        BIT(result[93],2)?" SUPPORTS_LIGHT_DETECT":"",
4460        BIT(result[93],1)?" SUPPORTS_READ_PRNU_DATA":"",
4461        BIT(result[93],0)?" FLATBED_MIRRORS_IMAGE":"");
4462 
4463   DBG (3, "attach: [94]    ESA5:%s%s%s%s%s%s%s%s\n",
4464        BIT(result[94],7)?" IGNORE_LINE_DIFFERENCE_FOR_ADF":"",
4465        BIT(result[94],6)?" NEEDS_SW_LINE_COLOR_PACK":"",
4466        BIT(result[94],5)?" SUPPORTS_DUPLEX_SCAN":"",
4467        BIT(result[94],4)?" INTERLACED_DUPLEX_SCAN":"",
4468        BIT(result[94],3)?" SUPPORTS_TWO_MODE_ADF_SCANS":"",
4469        BIT(result[94],2)?" SUPPORTS_TUNE_SCAN_LENGTH":"",
4470        BIT(result[94],1)?" SUPPORTS_SWITCH_STRIP_FOR_DESKEW":"", /* Kodak i80 only */
4471        BIT(result[94],0)?" SEARCHES_LEADING_SIDE_EDGE_BY_FIRMWARE":"");
4472 
4473   DBG (3, "attach: [95]    ESA6:%s%s%s%s%s%s%s%s\n",
4474        BIT(result[95],7)?" SUPPORTS_PAPER_SIZE_AUTO_DETECTION":"",
4475        BIT(result[95],6)?" SUPPORTS_DO_HOUSEKEEPING":"", /* Kodak i80 only */
4476        BIT(result[95],5)?" SUPPORTS_PAPER_LENGTH_SETTING":"", /* AV220, Kodak */
4477        BIT(result[95],4)?" SUPPORTS_PRE_GAMMA_LINEAR_CORRECTION":"",
4478        BIT(result[95],3)?" SUPPORTS_PREFEEDING":"", /*  OKI S9800 */
4479        BIT(result[95],2)?" SUPPORTS_GET_BACKGROUND_RASTER":"", /* AV220 et.al. */
4480        BIT(result[95],1)?" SUPPORTS_NVRAM_RESET":"",
4481        BIT(result[95],0)?" SUPPORTS_BATCH_SCAN":"");
4482 
4483   DBG (3, "attach: [128]    ESA7:%s%s%s%s%s%s%s%s\n",
4484        BIT(result[128],7)?" SUPPORTS_ADF_CONTINUOUS":"",
4485        BIT(result[128],6)?" SUPPORTS_YCbCr_COLOR":"",
4486        BIT(result[128],5)?" SUPPORTS_ADF_3PASS":"",
4487        BIT(result[128],4)?" SUPPORTS_TUNE_SCAN_LENGTH_HORIZ":"",
4488        BIT(result[128],3)?" SUPPORTS_READ_WRITE_ABILITY_PARAMETER":"",
4489        BIT(result[128],2)?" SUPPORTS_JOB_CONTROL":"",
4490        BIT(result[128],1)?" SUPPORTS_INF_LENGTH":"",
4491        BIT(result[128],0)?" ULTRA_SONIC_DOUBLE_FEED_DETECTION":"");
4492 
4493   DBG (3, "attach: [129]    YCbCr:%s%s%s%s%s%s%s%s\n",
4494        BIT(result[129],7)?" YCC4:2:0":"",
4495        BIT(result[129],6)?" YCC(profile2)":"",
4496        BIT(result[129],5)?" YCC(profile3)":"",
4497        BIT(result[129],4)?" YCC(profile4)":"",
4498        BIT(result[129],3)?" JPEG(profile1)":"",
4499        BIT(result[129],2)?" JPEG(profile2)":"",
4500        BIT(result[129],1)?" JPEG(profile3)":"",
4501        BIT(result[129],0)?" JPEG(profile4)":"");
4502 
4503   /* I have no idea how film scanner could reliably be detected -ReneR */
4504   if (dev->hw->feature_type & AV_FILMSCANNER) {
4505     dev->scanner_type = AV_FILM;
4506     dev->sane.type = "film scanner";
4507   }
4508   else if ( BIT(result[62],6) || BIT(result[62],4) ) {
4509     dev->scanner_type = AV_SHEETFEED;
4510     dev->sane.type =  "sheetfed scanner";
4511   }
4512   else {
4513     dev->scanner_type = AV_FLATBED;
4514     dev->sane.type = "flatbed scanner";
4515   }
4516 
4517   dev->inquiry_new_protocol = BIT (result[39],2);
4518   dev->inquiry_asic_type = (int) result[91];
4519 
4520   dev->inquiry_nvram_read = BIT(result[52],0);
4521   dev->inquiry_power_save_time = BIT(result[52],1);
4522 
4523   dev->inquiry_adf = BIT (result[62], 5);
4524   dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5);
4525   dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4);
4526   /* the first avision scanners (AV3200) do not set the interlaced bit */
4527   if (dev->inquiry_duplex && dev->inquiry_asic_type < AV_ASIC_C6)
4528     dev->inquiry_duplex_interlaced = 1;
4529 
4530   dev->inquiry_paper_length = BIT (result[95], 5);
4531   dev->inquiry_batch_scan = BIT (result[95], 0); /* AV122, DM152 */
4532 
4533   dev->inquiry_detect_accessories = BIT (result[93], 7);
4534 
4535   dev->inquiry_needs_calibration = BIT (result[50], 4);
4536 
4537   dev->inquiry_keeps_window = BIT (result[50], 1);
4538   if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_WINDOW)
4539     dev->inquiry_keeps_window = 0;
4540   if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_WINDOW)
4541     dev->inquiry_keeps_window = 1;
4542 
4543   dev->inquiry_needs_gamma = BIT (result[50], 3);
4544   dev->inquiry_keeps_gamma = BIT (result[50], 2);
4545   if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_GAMMA)
4546     dev->inquiry_keeps_gamma = 0;
4547   if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_GAMMA)
4548     dev->inquiry_keeps_gamma = 1;
4549 
4550   dev->inquiry_3x3_matrix = BIT (result[51], 1);
4551   dev->inquiry_needs_software_colorpack = BIT (result[50],5);
4552 
4553   dev->inquiry_needs_line_pack = BIT (result[94], 6);
4554 
4555   dev->inquiry_adf_need_mirror = BIT (result[51], 0);
4556   dev->inquiry_adf_bgr_order = BIT (result[93], 6);
4557   if (Avision_Device_List [model_num].feature_type & AV_ADF_BGR_ORDER_INVERT)
4558     dev->inquiry_adf_bgr_order = ! dev->inquiry_adf_bgr_order;
4559 
4560   dev->inquiry_light_detect = BIT (result[93], 2);
4561   dev->inquiry_light_control = BIT (result[50], 7);
4562   dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2);
4563 
4564   dev->inquiry_exposure_control = BIT(result[51],7);
4565   if (dev->scanner_type != AV_FILM && !(dev->hw->feature_type & AV_FORCE_FILM))
4566     dev->inquiry_exposure_control = 0;
4567   dev->inquiry_max_shading_target = get_double ( &(result[75]) );
4568 
4569   dev->inquiry_color_boundary = result[54];
4570   if (dev->inquiry_color_boundary == 0)
4571     dev->inquiry_color_boundary = 8;
4572 
4573   dev->inquiry_gray_boundary = result[55];
4574   if (dev->inquiry_gray_boundary == 0)
4575     dev->inquiry_gray_boundary = 8;
4576 
4577   dev->inquiry_dithered_boundary = result[59];
4578   if (dev->inquiry_dithered_boundary == 0)
4579     dev->inquiry_dithered_boundary = 8;
4580 
4581   dev->inquiry_thresholded_boundary = result[57];
4582   if (dev->inquiry_thresholded_boundary == 0)
4583     dev->inquiry_thresholded_boundary = 8;
4584 
4585   dev->inquiry_line_difference = result[53];
4586   /* compensation according to real world hardware */
4587   switch (dev->inquiry_asic_type)
4588   {
4589     case AV_ASIC_C2: /* HP 5300 */
4590     case AV_ASIC_C5: /* HP 53xx R2 */
4591       dev->inquiry_line_difference /= 2; /* HP 5300 */
4592       break;
4593     case AV_ASIC_C7:
4594       dev->inquiry_line_difference *= 2; /* AV610C2 */
4595       break;
4596     default:
4597       ;
4598   }
4599 
4600   if (dev->inquiry_new_protocol) {
4601     dev->inquiry_optical_res = get_double ( &(result[89]) );
4602     dev->inquiry_max_res = get_double ( &(result[44]) );
4603   }
4604   else {
4605     dev->inquiry_optical_res = result[37] * 100;
4606     dev->inquiry_max_res = result[38] * 100;
4607   }
4608 
4609   /* fixup max res */
4610   if (dev->inquiry_optical_res > dev->inquiry_max_res) {
4611     DBG (1, "Inquiry optical resolution > max_resolution, adjusting!\n");
4612     dev->inquiry_max_res = dev->inquiry_optical_res;
4613   }
4614 
4615   if (dev->inquiry_optical_res == 0)
4616     {
4617       DBG (1, "Inquiry optical resolution is invalid!\n");
4618       if (dev->hw->feature_type & AV_FORCE_FILM)
4619 	dev->inquiry_optical_res = 2438; /* verify */
4620       if (dev->scanner_type == AV_SHEETFEED)
4621 	dev->inquiry_optical_res = 300;
4622       else
4623 	dev->inquiry_optical_res = 600;
4624     }
4625   if (dev->inquiry_max_res == 0) {
4626     DBG (1, "Inquiry max resolution is invalid, using 1200 dpi!\n");
4627     dev->inquiry_max_res = 1200;
4628   }
4629 
4630   DBG (1, "attach: optical resolution set to: %d dpi\n", dev->inquiry_optical_res);
4631   DBG (1, "attach: max resolution set to: %d dpi\n", dev->inquiry_max_res);
4632 
4633   if (BIT(result[60],6))
4634     dev->inquiry_channels_per_pixel = 3;
4635   else if (BIT(result[60],7))
4636     dev->inquiry_channels_per_pixel = 1;
4637   else if ( ((result[36] >> 4) & 0x7) > 0)
4638     dev->inquiry_channels_per_pixel = 3;
4639   else
4640     dev->inquiry_channels_per_pixel = 1;
4641 
4642   if (BIT(result[61],1))
4643     dev->inquiry_bits_per_channel = 16;
4644   else if (BIT(result[61],2))
4645     dev->inquiry_bits_per_channel = 12;
4646   else if (BIT(result[61],3))
4647     dev->inquiry_bits_per_channel = 10;
4648   else if (BIT(result[61],4))
4649     dev->inquiry_bits_per_channel = 8;
4650   else if (BIT(result[61],5))
4651     dev->inquiry_bits_per_channel = 6;
4652   else if (BIT(result[61],6))
4653     dev->inquiry_bits_per_channel = 4;
4654   else if (BIT(result[61],7))
4655     dev->inquiry_bits_per_channel = 1;
4656   else
4657     dev->inquiry_bits_per_channel = 8; /* default for old scanners */
4658 
4659   if (dev->hw->feature_type & AV_12_BIT_MODE)
4660     dev->inquiry_bits_per_channel = 12;
4661 
4662   if (! (dev->hw->feature_type & AV_GRAY_MODES))
4663     dev->inquiry_no_gray_modes = BIT(result[93],5);
4664 
4665   DBG (1, "attach: max channels per pixel: %d, max bits per channel: %d\n",
4666     dev->inquiry_channels_per_pixel, dev->inquiry_bits_per_channel);
4667 
4668   if (! (dev->hw->feature_type & AV_NO_BUTTON))
4669     dev->inquiry_buttons = result[92];
4670 
4671   /* get max x/y ranges for the different modes */
4672   {
4673     double base_dpi; /* TODO: make int */
4674     if (dev->scanner_type != AV_FILM) {
4675       base_dpi = AVISION_BASE_RES;
4676     } else {
4677       /* ZP: The right number is 2820, whether it is 40-41, 42-43, 44-45,
4678        * 46-47 or 89-90 I don't know but I would bet for the last !
4679        * ReneR: OK. We use it via the optical_res which we need anyway ...
4680        */
4681       base_dpi = dev->inquiry_optical_res;
4682     }
4683 
4684     /* .1 to slightly increase the size to match the one of American standard paper
4685        formats that would otherwise be .1 mm too large to scan ... */
4686     dev->inquiry_x_ranges [AV_NORMAL_DIM] =
4687       (double)get_double (&(result[81])) * MM_PER_INCH / base_dpi + .1;
4688     dev->inquiry_y_ranges [AV_NORMAL_DIM] =
4689       (double)get_double (&(result[83])) * MM_PER_INCH / base_dpi;
4690 
4691     dev->inquiry_x_ranges [AV_TRANSPARENT_DIM] =
4692       (double)get_double (&(result[77])) * MM_PER_INCH / base_dpi + .1;
4693     dev->inquiry_y_ranges [AV_TRANSPARENT_DIM] =
4694       (double)get_double (&(result[79])) * MM_PER_INCH / base_dpi;
4695 
4696     dev->inquiry_x_ranges [AV_ADF_DIM] =
4697       (double)get_double (&(result[85])) * MM_PER_INCH / base_dpi + .1;
4698     dev->inquiry_y_ranges [AV_ADF_DIM] =
4699       (double)get_double (&(result[87])) * MM_PER_INCH / base_dpi;
4700   }
4701 
4702   dev->inquiry_tune_scan_length = BIT(result[94],2);
4703   if (Avision_Device_List [model_num].feature_type & AV_NO_TUNE_SCAN_LENGTH)
4704     dev->inquiry_tune_scan_length = 0;
4705 
4706   dev->inquiry_background_raster = BIT(result[95],2);
4707 
4708   if (dev->hw->feature_type & AV_NO_BACKGROUND)
4709     dev->inquiry_background_raster = 0;
4710 
4711   if (dev->inquiry_background_raster) {
4712     dev->inquiry_background_raster_pixel =
4713       get_double(&(result[85])) * dev->inquiry_optical_res / AVISION_BASE_RES;
4714   }
4715 
4716   /* check if x/y ranges are valid :-((( */
4717   {
4718     source_mode_dim mode;
4719 
4720     for (mode = AV_NORMAL_DIM; mode < AV_SOURCE_MODE_DIM_LAST; ++ mode)
4721       {
4722 	if (dev->inquiry_x_ranges [mode] != 0 &&
4723 	    dev->inquiry_y_ranges [mode] != 0)
4724 	  {
4725 	    DBG (3, "attach: x/y-range for mode %d is valid!\n", mode);
4726 	    if (force_a4) {
4727 	      DBG (1, "attach: \"force_a4\" found! Using default (ISO A4).\n");
4728 	      dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH;
4729 	      dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH;
4730 	    } else if (force_a3) {
4731 	      DBG (1, "attach: \"force_a3\" found! Using default (ISO A3).\n");
4732 	      dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH;
4733 	      dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH;
4734 	    }
4735 	  }
4736 	else /* mode is invalid */
4737 	  {
4738 	    DBG (1, "attach: x/y-range for mode %d is invalid! Using a default.\n", mode);
4739 	    if (dev->hw->feature_type & AV_FORCE_A3) {
4740 	      dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH;
4741 	      dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH;
4742 	    }
4743 	    else if (dev->hw->feature_type & AV_FORCE_FILM) {
4744 	      dev->inquiry_x_ranges [mode] = FILM_X_RANGE * MM_PER_INCH;
4745 	      dev->inquiry_y_ranges [mode] = FILM_Y_RANGE * MM_PER_INCH;
4746 	    }
4747 	    else {
4748 	      dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH;
4749 
4750 	      if (dev->scanner_type == AV_SHEETFEED)
4751 		dev->inquiry_y_ranges [mode] = SHEETFEED_Y_RANGE * MM_PER_INCH;
4752 	      else
4753 		dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH;
4754 	    }
4755 	  }
4756 	DBG (1, "attach: Mode %d range is now: %f x %f mm.\n",
4757 	     mode,
4758 	     dev->inquiry_x_ranges [mode], dev->inquiry_y_ranges [mode]);
4759       } /* end for all modes */
4760   }
4761 
4762   /* We need a bigger buffer for USB devices, since they seem to have
4763      a firmware bug and do not support reading the calibration data in
4764      tiny chunks */
4765   if (av_con.connection_type == AV_USB)
4766     dev->scsi_buffer_size = 1024 * 1024; /* or 0x10000, used by AV Windows driver during background raster read, ... ? */
4767   else
4768     dev->scsi_buffer_size = sanei_scsi_max_request_size;
4769 
4770   if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980)
4771     dev->read_stripe_size = 16;
4772   else if (dev->inquiry_asic_type >= AV_ASIC_C5)
4773     dev->read_stripe_size = 32;
4774   else  /* tested on AV3200 with it's max of 300dpi @color */
4775     dev->read_stripe_size = 8; /* maybe made dynamic on scan res ... */
4776 
4777   /* normally the data_dq is 0x0a0d - but some newer scanner hang with it ... */
4778   if (dev->inquiry_new_protocol) /* TODO: match on ASIC? which model hung? */
4779     dev->data_dq = 0x0a0d;
4780   else
4781     dev->data_dq = 0;
4782 
4783   avision_close (&av_con);
4784 
4785   ++ num_devices;
4786   dev->next = first_dev;
4787   first_dev = dev;
4788   if (devp)
4789     *devp = dev;
4790 
4791   return SANE_STATUS_GOOD;
4792 
4793  close_scanner_and_return:
4794   avision_close (&av_con);
4795 
4796   return status;
4797 }
4798 
4799 
4800 static SANE_Status
get_tune_scan_length(Avision_Scanner * s)4801 get_tune_scan_length (Avision_Scanner* s)
4802 {
4803   SANE_Status status;
4804   int i;
4805 
4806   struct command_read rcmd;
4807   size_t size;
4808 
4809   struct max_value {
4810     uint8_t max [2];
4811   } payload;
4812 
4813   /* turn on the light */
4814   DBG (3, "get_tune_scan_length:\n");
4815 
4816   memset (&rcmd, 0, sizeof (rcmd));
4817   size = sizeof (payload);
4818 
4819   rcmd.opc = AVISION_SCSI_READ;
4820   rcmd.datatypecode = 0xD2; /* Read General Ability/Parameter */
4821 
4822   for (i = 1; i <= 8; ++i) {
4823     memset (&payload, 0, sizeof (payload));
4824 
4825     set_double (rcmd.datatypequal, i); /* type */
4826     set_triple (rcmd.transferlen, size);
4827 
4828     status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd),
4829 			  0, 0, &payload, &size);
4830 
4831     if (status != SANE_STATUS_GOOD) {
4832       DBG (1, "get_tune_scan_length: read %d failed (%s)\n", i, sane_strstatus (status));
4833       return status;
4834     }
4835     DBG (1, "get_tune_scan_length: %d: %d\n", i, get_double (payload.max));
4836   }
4837 
4838   return SANE_STATUS_GOOD;
4839 }
4840 
4841 static SANE_Status
send_tune_scan_length(Avision_Scanner * s)4842 send_tune_scan_length (Avision_Scanner* s)
4843 {
4844   Avision_Device* dev = s->hw;
4845 
4846   int top, bottom, dpi;
4847   double offset = 0;
4848 
4849   SANE_Status status;
4850   size_t size;
4851   struct command_send scmd;
4852   struct truncate_attach {
4853     uint8_t vertical [2];
4854  /*   uint8_t horizontal [2]; not send by the Windows driver, yet */
4855   } payload;
4856 
4857   DBG (3, "send_tune_scan_length:\n");
4858 
4859   memset (&scmd, 0, sizeof (scmd));
4860 
4861   size = sizeof (payload);
4862   scmd.opc = AVISION_SCSI_SEND;
4863   scmd.datatypecode = 0x96; /* Attach/Truncate head(left) of scan length */
4864   set_triple (scmd.transferlen, size);
4865 
4866   /* the SPEC says optical DPI, but real world measuring suggests it is 1200
4867      as in the window descriptor.
4868      MN: This is not true for at least Kodak i1120 where it is optical DPI
4869   */
4870   dpi = 1200;
4871   if (dev->hw->feature_type & AV_OVERSCAN_OPTDPI)
4872     dpi = dev->inquiry_optical_res;
4873 
4874   top = dpi * SANE_UNFIX (s->val[OPT_OVERSCAN_TOP].w) / MM_PER_INCH;
4875   DBG (3, "send_tune_scan_length: top: %d\n", top);
4876 
4877   /* top offset compensation */
4878   if (dev->adf_offset_compensation) {
4879     if (s->avdimen.interlaced_duplex)
4880       offset += fmax(0, fmax(dev->hw->offset.duplex.front.top,
4881                              dev->hw->offset.duplex.rear.top) );
4882     else if (s->source_mode == AV_ADF)
4883       offset += fmax(0, dev->hw->offset.front.top);
4884 
4885     /* first page offset */
4886     if (dev->hw->offset.first > 0)
4887       offset += dev->hw->offset.first;
4888 
4889     /* convert to lines */
4890     int top_offset = dpi * offset / MM_PER_INCH;
4891     top += top_offset;
4892     DBG (3, "send_tune_scan_length: top offset: %d\n", top_offset);
4893   }
4894 
4895   set_double (scmd.datatypequal, 0x0001); /* attach, 0x000 is shorten */
4896   set_double (payload.vertical, top);
4897   /* set_double (payload.horizontal, 0); */
4898 
4899   /* we always send it, even for 0 as the scanner keeps it in RAM and
4900      previous runs could already have set something */
4901 
4902   status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
4903 			&payload, sizeof (payload), 0, 0);
4904 
4905   if (status != SANE_STATUS_GOOD) {
4906     DBG (1, "send_tune_scan_length: send top/left failed (%s)\n", sane_strstatus (status));
4907     return status;
4908   }
4909 
4910   scmd.datatypecode = 0x95; /* Attach/Truncate tail(right) of scan length */
4911   bottom = dpi * SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w) / MM_PER_INCH;
4912   DBG (3, "send_tune_scan_length: bottom: %d\n", bottom);
4913 
4914   /* bottom offset compensation */
4915   offset = 0;
4916   if (dev->adf_offset_compensation) {
4917     if (s->avdimen.interlaced_duplex)
4918       offset += fmax(0, fmax(dev->hw->offset.duplex.front.bottom,
4919                              dev->hw->offset.duplex.rear.bottom) );
4920     else if (s->source_mode == AV_ADF)
4921       offset += fmax(0, dev->hw->offset.front.bottom);
4922 
4923     /* first page offset */
4924     if (dev->hw->offset.first < 0)
4925       offset += fabs(dev->hw->offset.first);
4926 
4927     /* convert to lines */
4928     int bottom_offset = dpi * offset / MM_PER_INCH;
4929     bottom += bottom_offset;
4930     DBG (3, "send_tune_scan_length: bottom offset: %d\n", bottom_offset);
4931   }
4932 
4933   set_double (payload.vertical, bottom);
4934   /*set_double (payload.horizontal, 0); */
4935 
4936   size = sizeof (payload);
4937   status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
4938 			&payload, sizeof (payload), 0, 0);
4939 
4940   if (status != SANE_STATUS_GOOD) {
4941     DBG (1, "send_tune_scan_length: send bottom/right failed (%s)\n", sane_strstatus (status));
4942     return status;
4943   }
4944 
4945   return SANE_STATUS_GOOD;
4946 }
4947 
4948 static SANE_Status
additional_probe(Avision_Scanner * s)4949 additional_probe (Avision_Scanner* s)
4950 {
4951   Avision_Device* dev = s->hw;
4952 
4953   /* we should wait until the scanner is ready before we
4954      perform further actions */
4955 
4956   SANE_Status status;
4957   /* try to retrieve additional accessory information */
4958   if (dev->inquiry_detect_accessories) {
4959     status = get_accessories_info (s);
4960     if (status != SANE_STATUS_GOOD)
4961       return status;
4962   }
4963 
4964   /* for a film scanner try to retrieve additional frame information */
4965   if (dev->scanner_type == AV_FILM) {
4966     status = get_frame_info (s);
4967     if (status != SANE_STATUS_GOOD)
4968       return status;
4969   }
4970 
4971   /* no scanner did support this so far: tried on AV220, DM152 */
4972   if (0 && dev->inquiry_duplex) {
4973     status = get_duplex_info (s);
4974     if (status != SANE_STATUS_GOOD)
4975       return status;
4976   }
4977 
4978   /* get overscan ("head/tail tune") information: hangs AV220, zeros on AV122 */
4979   if (0 && dev->inquiry_tune_scan_length) {
4980     status = get_tune_scan_length (s);
4981     if (status != SANE_STATUS_GOOD)
4982       return status;
4983   }
4984 
4985   /* create dynamic *-mode entries */
4986   if (!dev->inquiry_no_gray_modes)
4987   {
4988     if (dev->inquiry_bits_per_channel > 0) {
4989       add_color_mode (dev, AV_THRESHOLDED, SANE_VALUE_SCAN_MODE_LINEART);
4990       add_color_mode (dev, AV_DITHERED, "Dithered");
4991     }
4992 
4993     if (dev->inquiry_bits_per_channel >= 8)
4994       add_color_mode (dev, AV_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY);
4995 
4996     if (dev->inquiry_bits_per_channel == 12)
4997       add_color_mode (dev, AV_GRAYSCALE12, "12bit Gray");
4998 
4999     if (dev->inquiry_bits_per_channel >= 16)
5000       add_color_mode (dev, AV_GRAYSCALE16, "16bit Gray");
5001   }
5002 
5003   if (dev->inquiry_channels_per_pixel > 1) {
5004     add_color_mode (dev, AV_TRUECOLOR, SANE_VALUE_SCAN_MODE_COLOR);
5005 
5006     if (dev->inquiry_bits_per_channel == 12)
5007       add_color_mode (dev, AV_TRUECOLOR12, "12bit Color");
5008 
5009     if (dev->inquiry_bits_per_channel >= 16)
5010       add_color_mode (dev, AV_TRUECOLOR16, "16bit Color");
5011   }
5012 
5013   /* now choose the default mode - avoiding the 12/16 bit modes */
5014   dev->color_list_default = last_color_mode (dev);
5015   if (dev->inquiry_bits_per_channel > 8 && dev->color_list_default > 0) {
5016     dev->color_list_default--;
5017   }
5018 
5019   if (dev->scanner_type == AV_SHEETFEED)
5020     {
5021       add_source_mode (dev, AV_ADF, "ADF Front");
5022     }
5023   else
5024     {
5025       add_source_mode (dev, AV_NORMAL, "Normal");
5026 
5027       if (dev->inquiry_light_box)
5028 	add_source_mode (dev, AV_TRANSPARENT, "Transparency");
5029 
5030       if (dev->inquiry_adf)
5031         add_source_mode (dev, AV_ADF, "ADF Front");
5032     }
5033 
5034   if (dev->inquiry_duplex) {
5035     if (dev->inquiry_duplex_interlaced && !(dev->hw->feature_type & AV_NO_REAR))
5036       add_source_mode (dev, AV_ADF_REAR, "ADF Back");
5037     add_source_mode (dev, AV_ADF_DUPLEX, "ADF Duplex");
5038   }
5039 
5040   return SANE_STATUS_GOOD;
5041 }
5042 
5043 static SANE_Status
get_calib_format(Avision_Scanner * s,struct calibration_format * format)5044 get_calib_format (Avision_Scanner* s, struct calibration_format* format)
5045 {
5046   SANE_Status status;
5047 
5048   struct command_read rcmd;
5049   uint8_t result [32];
5050   size_t size;
5051 
5052   DBG (3, "get_calib_format:\n");
5053 
5054   size = sizeof (result);
5055 
5056   memset (&rcmd, 0, sizeof (rcmd));
5057   rcmd.opc = AVISION_SCSI_READ;
5058   rcmd.datatypecode = 0x60; /* get calibration format */
5059   set_double (rcmd.datatypequal, s->hw->data_dq);
5060   set_triple (rcmd.transferlen, size);
5061 
5062   DBG (3, "get_calib_format: read_data: %lu bytes\n", (u_long) size);
5063   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
5064   if (status != SANE_STATUS_GOOD || size != sizeof (result) ) {
5065     DBG (1, "get_calib_format: read calib. info failed (%s)\n",
5066 	 sane_strstatus (status) );
5067     return status;
5068   }
5069 
5070   debug_print_calib_format (3, "get_calib_format", result);
5071 
5072   format->pixel_per_line = get_double (&(result[0]));
5073   format->bytes_per_channel = result[2];
5074   format->lines = result[3];
5075   format->flags = result[4];
5076   format->ability1 = result[5];
5077   format->r_gain = result[6];
5078   format->g_gain = result[7];
5079   format->b_gain = result[8];
5080   format->r_shading_target = get_double (&(result[9]));
5081   format->g_shading_target = get_double (&(result[11]));
5082   format->b_shading_target = get_double (&(result[13]));
5083   format->r_dark_shading_target = get_double (&(result[15]));
5084   format->g_dark_shading_target = get_double (&(result[17]));
5085   format->b_dark_shading_target = get_double (&(result[19]));
5086 
5087   /* now translate to normal! */
5088   /* firmware return R--RG--GB--B with 3 line count */
5089   /* software format it as 1 line if true color scan */
5090   /* only line interleave format to be supported */
5091 
5092   if (color_mode_is_color (s->c_mode) || BIT(format->ability1, 3)) {
5093     format->channels = 3;
5094     format->lines /= 3; /* line interleave */
5095   }
5096   else
5097     format->channels = 1;
5098 
5099   DBG (3, "get_calib_format: channels: %d\n", format->channels);
5100 
5101   return SANE_STATUS_GOOD;
5102 }
5103 
5104 static SANE_Status
get_calib_data(Avision_Scanner * s,uint8_t data_type,uint8_t * calib_data,size_t calib_size)5105 get_calib_data (Avision_Scanner* s, uint8_t data_type,
5106 		uint8_t* calib_data,
5107 		size_t calib_size)
5108 {
5109   SANE_Status status;
5110   uint8_t *calib_ptr;
5111 
5112   size_t get_size, data_size, chunk_size;
5113 
5114   struct command_read rcmd;
5115 
5116   chunk_size = calib_size;
5117 
5118   DBG (3, "get_calib_data: type %x, size %lu, chunk_size: %lu\n",
5119        data_type, (u_long) calib_size, (u_long) chunk_size);
5120 
5121   memset (&rcmd, 0, sizeof (rcmd));
5122 
5123   rcmd.opc = AVISION_SCSI_READ;
5124   rcmd.datatypecode = data_type;
5125   set_double (rcmd.datatypequal, s->hw->data_dq);
5126 
5127   calib_ptr = calib_data;
5128   get_size = chunk_size;
5129   data_size = calib_size;
5130 
5131   while (data_size) {
5132     if (get_size > data_size)
5133       get_size = data_size;
5134 
5135     read_constrains(s, get_size);
5136 
5137     set_triple (rcmd.transferlen, get_size);
5138 
5139     DBG (3, "get_calib_data: Reading %ld bytes calibration data\n",
5140          (long)get_size);
5141 
5142     status = avision_cmd (&s->av_con, &rcmd,
5143 			  sizeof (rcmd), 0, 0, calib_ptr, &get_size);
5144     if (status != SANE_STATUS_GOOD) {
5145       DBG (1, "get_calib_data: read data failed (%s)\n",
5146 	   sane_strstatus (status));
5147       return status;
5148     }
5149 
5150     DBG (3, "get_calib_data: Got %ld bytes calibration data\n", (long)get_size);
5151 
5152     data_size -= get_size;
5153     calib_ptr += get_size;
5154   }
5155 
5156   return SANE_STATUS_GOOD;
5157 }
5158 
5159 static SANE_Status
set_calib_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * dark_data,uint8_t * white_data)5160 set_calib_data (Avision_Scanner* s, struct calibration_format* format,
5161 		uint8_t* dark_data, uint8_t* white_data)
5162 {
5163   Avision_Device* dev = s->hw;
5164 
5165   const int elements_per_line = format->pixel_per_line * format->channels;
5166 
5167   SANE_Status status;
5168 
5169   uint8_t send_type;
5170   uint16_t send_type_q;
5171 
5172   struct command_send scmd;
5173 
5174   int i;
5175 
5176   DBG (3, "set_calib_data:\n");
5177 
5178   send_type = 0x82; /* download calibration data */
5179 
5180   /* do we use a color mode? */
5181   if (format->channels > 1) {
5182     send_type_q = 0x12; /* color calib data */
5183   }
5184   else {
5185     if (dev->hw->feature_type & AV_GRAY_CALIB_BLUE)
5186       send_type_q = 0x2; /* gray/bw calib data on the blue channel (AV610) */
5187     else
5188       send_type_q = 0x11; /* gray/bw calib data */
5189   }
5190 
5191   memset (&scmd, 0x00, sizeof (scmd));
5192   scmd.opc = AVISION_SCSI_SEND;
5193   scmd.datatypecode = send_type;
5194 
5195   /* data corrections due to dark calibration data merge */
5196   if (BIT (format->ability1, 2) ) {
5197     DBG (3, "set_calib_data: merging dark calibration data\n");
5198     for (i = 0; i < elements_per_line; ++i) {
5199       uint16_t value_orig = get_double_le (white_data + i*2);
5200       uint16_t value_new = value_orig;
5201 
5202       value_new &= 0xffc0;
5203       value_new |= (get_double_le (dark_data + i*2) >> 10) & 0x3f;
5204 
5205       DBG (9, "set_calib_data: element %d, dark difference %d\n",
5206 	   i, value_orig - value_new);
5207 
5208       set_double_le ((white_data + i*2), value_new);
5209     }
5210   }
5211 
5212   /* send data in one command? */
5213   /* FR: HP5370 reports one-pass, but needs multi (or other format in single) */
5214   if (format->channels == 1 ||
5215       ( ( (dev->hw->feature_type & AV_ONE_CALIB_CMD) ||
5216 	  ! BIT(format->ability1, 0) ) &&
5217 	! (dev->hw->feature_type & AV_MULTI_CALIB_CMD) ) )
5218     /* one command (most scanners) */
5219     {
5220       size_t send_size = elements_per_line * 2;
5221       DBG (3, "set_calib_data: all channels in one command\n");
5222       DBG (3, "set_calib_data: send_size: %lu\n", (u_long) send_size);
5223 
5224       memset (&scmd, 0, sizeof (scmd) );
5225       scmd.opc = AVISION_SCSI_SEND;
5226       scmd.datatypecode = send_type;
5227       set_double (scmd.datatypequal, send_type_q);
5228       set_triple (scmd.transferlen, send_size);
5229 
5230       status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5231 			    (char*) white_data, send_size, 0, 0);
5232       /* not return immediately to free mem at the end */
5233     }
5234   else /* send data channel by channel (some USB ones) */
5235     {
5236       int conv_out_size = format->pixel_per_line * 2;
5237       uint16_t* conv_out_data; /* here it is save to use 16bit data
5238 				   since we only move whole words around */
5239 
5240       DBG (3, "set_calib_data: channels in single commands\n");
5241 
5242       conv_out_data =  (uint16_t*) malloc (conv_out_size);
5243       if (!conv_out_data) {
5244 	status = SANE_STATUS_NO_MEM;
5245       }
5246       else {
5247 	int channel;
5248 	for (channel = 0; channel < 3; ++ channel)
5249 	  {
5250 	    int i;
5251 
5252 	    /* no need for endianness handling since whole word copy */
5253 	    uint16_t* casted_avg_data = (uint16_t*) white_data;
5254 
5255 	    DBG (3, "set_calib_data_calibration: channel: %i\n", channel);
5256 
5257 	    for (i = 0; i < format->pixel_per_line; ++ i)
5258 	      conv_out_data [i] = casted_avg_data [i * 3 + channel];
5259 
5260 	    DBG (3, "set_calib_data: sending %i bytes now\n",
5261 		 conv_out_size);
5262 
5263 	    memset (&scmd, 0, sizeof (scmd));
5264 	    scmd.opc = AVISION_SCSI_SEND;
5265 	    scmd.datatypecode = send_type; /* send calibration data */
5266 	    set_double (scmd.datatypequal, channel);
5267 	    set_triple (scmd.transferlen, conv_out_size);
5268 
5269 	    status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5270 				  conv_out_data, conv_out_size, 0, 0);
5271 	    if (status != SANE_STATUS_GOOD) {
5272 	      DBG (3, "set_calib_data: send_data failed (%s)\n",
5273 		   sane_strstatus (status));
5274 	      /* not return immediately to free mem at the end */
5275 	    }
5276 	  } /* end for each channel */
5277 	free (conv_out_data);
5278       } /* end else send calib data*/
5279     }
5280 
5281   return SANE_STATUS_GOOD;
5282 }
5283 
5284 /* Sort data pixel by pixel and average first 2/3 of the data.
5285    The caller has to free return pointer. R,G,B pixels
5286    interleave to R,G,B line interleave.
5287 
5288    The input data data is in 16 bits little endian, always.
5289    That is a = b[1] << 8 + b[0] in all system.
5290 
5291    We convert it to SCSI high-endian (big-endian) since we use it all
5292    over the place anyway .... - Sorry for this mess. */
5293 
5294 static uint8_t*
sort_and_average(struct calibration_format * format,uint8_t * data)5295 sort_and_average (struct calibration_format* format, uint8_t* data)
5296 {
5297   const int elements_per_line = format->pixel_per_line * format->channels;
5298   const int stride = format->bytes_per_channel * elements_per_line;
5299   int i, line;
5300 
5301   uint8_t *sort_data, *avg_data;
5302 
5303   DBG (1, "sort_and_average:\n");
5304 
5305   if (!format || !data)
5306     return NULL;
5307 
5308   sort_data = malloc (format->lines * 2);
5309   if (!sort_data)
5310     return NULL;
5311 
5312   avg_data = malloc (elements_per_line * 2);
5313   if (!avg_data) {
5314     free (sort_data);
5315     return NULL;
5316   }
5317 
5318   /* for each pixel */
5319   for (i = 0; i < elements_per_line; ++ i)
5320     {
5321       uint8_t* ptr1 = data + i * format->bytes_per_channel;
5322       uint16_t temp;
5323 
5324       /* copy all lines for pixel i into the linear array sort_data */
5325       for (line = 0; line < format->lines; ++ line) {
5326 	uint8_t* ptr2 = ptr1 + line * stride; /* pixel */
5327 
5328 	if (format->bytes_per_channel == 1)
5329 	  temp = 0xffff * *ptr2 / 255;
5330 	else
5331 	  temp = get_double_le (ptr2);	  /* little-endian! */
5332 	set_double ((sort_data + line*2), temp); /* store big-endian */
5333 	/* DBG (7, "ReneR to sort: %x\n", temp); */
5334       }
5335 
5336       temp = bubble_sort (sort_data, format->lines);
5337       /* DBG (7, "ReneR averaged: %x\n", temp); */
5338       set_double ((avg_data + i*2), temp); /* store big-endian */
5339     }
5340 
5341   free ((void *) sort_data);
5342   return avg_data;
5343 }
5344 
5345 /* shading data is 16bits little endian format when send/read from firmware */
5346 static void
compute_dark_shading_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * data)5347 compute_dark_shading_data (Avision_Scanner* s,
5348 			   struct calibration_format* format, uint8_t* data)
5349 {
5350   uint16_t map_value = DEFAULT_DARK_SHADING;
5351   uint16_t rgb_map_value[3];
5352 
5353   int elements_per_line, i;
5354 
5355   DBG (3, "compute_dark_shading_data:\n");
5356 
5357   if (s->hw->inquiry_max_shading_target != INVALID_DARK_SHADING)
5358     map_value = s->hw->inquiry_max_shading_target << 8;
5359 
5360   rgb_map_value[0] = format->r_dark_shading_target;
5361   rgb_map_value[1] = format->g_dark_shading_target;
5362   rgb_map_value[2] = format->b_dark_shading_target;
5363 
5364   for (i = 0; i < format->channels; ++i) {
5365     if (rgb_map_value[i] == INVALID_DARK_SHADING)
5366       rgb_map_value[i] = map_value;
5367   }
5368 
5369   if (format->channels == 1) {
5370     /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */
5371     rgb_map_value[0] = rgb_map_value[1] = rgb_map_value[2] = rgb_map_value[1];
5372   }
5373 
5374   elements_per_line = format->pixel_per_line * format->channels;
5375 
5376   /* Check line interleave or pixel interleave. */
5377   /* It seems no ASIC use line interleave right now. */
5378   /* Avision SCSI protocol document has bad description. */
5379   for (i = 0; i < elements_per_line; ++i)
5380     {
5381       uint16_t tmp_data = get_double_le((data + i*2));
5382       if (tmp_data > rgb_map_value[i % 3]) {
5383 	set_double ((data + i*2), tmp_data - rgb_map_value[i % 3]);
5384       }
5385       else {
5386 	set_double ((data + i*2), 0);
5387       }
5388     }
5389 }
5390 
5391 static void
compute_white_shading_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * data)5392 compute_white_shading_data (Avision_Scanner* s,
5393 			    struct calibration_format* format, uint8_t* data)
5394 {
5395   int i;
5396   uint16_t inquiry_mst = DEFAULT_WHITE_SHADING;
5397   uint16_t mst[3];
5398 
5399   int elements_per_line = format->pixel_per_line * format->channels;
5400 
5401   /* debug counter */
5402   int values_invalid = 0;
5403   int values_limitted = 0;
5404 
5405   DBG (3, "compute_white_shading_data:\n");
5406 
5407   if (s->hw->inquiry_max_shading_target != INVALID_WHITE_SHADING)
5408     inquiry_mst = s->hw->inquiry_max_shading_target << 4;
5409 
5410   mst[0] = format->r_shading_target;
5411   mst[1] = format->g_shading_target;
5412   mst[2] = format->b_shading_target;
5413 
5414   for (i = 0; i < 3; ++i) {
5415     if (mst[i] == INVALID_WHITE_SHADING) /* mst[i] > MAX_WHITE_SHADING) */  {
5416       DBG (3, "compute_white_shading_data: target %d invalid (%x) using inquiry (%x)\n",
5417 	   i, mst[i], inquiry_mst);
5418       mst[i] = inquiry_mst;
5419     }
5420     /* some firmware versions seems to return the bytes swapped? */
5421     else if (mst[i] < 0x110) {
5422       uint8_t* swap_mst = (uint8_t*) &mst[i];
5423       uint8_t low_nibble_mst = swap_mst [0];
5424       swap_mst [0] = swap_mst[1];
5425       swap_mst [1] = low_nibble_mst;
5426 
5427       DBG (3, "compute_white_shading_data: target %d: bytes swapped.\n", i);
5428     }
5429     if (mst[i] < DEFAULT_WHITE_SHADING / 2) {
5430       DBG (3, "compute_white_shading_data: target %d: too low (%d) using default (%d).\n",
5431 	   i, mst[i], DEFAULT_WHITE_SHADING);
5432       mst[i] = DEFAULT_WHITE_SHADING;
5433     }
5434     else
5435       DBG (3, "compute_white_shading_data: target %d: %x\n", i, mst[0]);
5436   }
5437 
5438   /* some Avision example code was present here until SANE/Avision
5439    * BUILD 57. */
5440 
5441   if (format->channels == 1) {
5442     /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */
5443     mst[0] = mst[1] = mst[2] = mst[1];
5444   }
5445 
5446   /* calculate calibration data */
5447   for (i = 0; i < elements_per_line; ++ i)
5448     {
5449       int result;
5450       /* calculate calibration value for pixel i */
5451       uint16_t tmp_data = get_double((data + i*2));
5452 
5453       if (tmp_data == INVALID_WHITE_SHADING) {
5454        	tmp_data = DEFAULT_WHITE_SHADING;
5455 	++ values_invalid;
5456       }
5457 
5458       result = ( (int)mst[i % 3] * WHITE_MAP_RANGE / (tmp_data + 0.5));
5459 
5460       /* sanity check for over-amplification, clipping */
5461       if (result > MAX_WHITE_SHADING) {
5462 	result = WHITE_MAP_RANGE;
5463 	++ values_limitted;
5464       }
5465 
5466       /* for visual debugging ... */
5467       if (static_calib_list [i % 3] == SANE_TRUE)
5468 	result = 0xA000;
5469 
5470       /* the output to the scanner will be 16 bit little endian again */
5471       set_double_le ((data + i*2), result);
5472     }
5473   DBG (3, "compute_white_shading_data: %d invalid, %d limited\n",
5474        values_invalid, values_limitted);
5475 }
5476 
5477 /* old_r_calibration was here until SANE/Avision BUILD 90 */
5478 
5479 static SANE_Status
normal_calibration(Avision_Scanner * s)5480 normal_calibration (Avision_Scanner* s)
5481 {
5482   SANE_Status status;
5483 
5484   struct calibration_format calib_format;
5485 
5486   int calib_data_size, calib_bytes_per_line;
5487   uint8_t read_type;
5488   uint8_t *calib_tmp_data;
5489 
5490   DBG (1, "normal_calibration:\n");
5491 
5492   /* get calibration format and data */
5493   status = get_calib_format (s, &calib_format);
5494   if (status != SANE_STATUS_GOOD)
5495     return status;
5496 
5497   /* check if need do calibration */
5498   if (calib_format.flags != 1 && !(s->hw->hw->feature_type & AV_FORCE_CALIB)) {
5499     DBG (1, "normal_calibration: Scanner claims no calibration needed -> skipped!\n");
5500     return SANE_STATUS_GOOD;
5501   }
5502 
5503   /* calculate calibration data size for read from scanner */
5504   /* size = lines * bytes_per_channel * pixels_per_line * channel */
5505   calib_bytes_per_line = calib_format.bytes_per_channel *
5506     calib_format.pixel_per_line * calib_format.channels;
5507 
5508   calib_data_size = calib_format.lines * calib_bytes_per_line;
5509 
5510   calib_tmp_data = malloc (calib_data_size);
5511   if (!calib_tmp_data)
5512     return SANE_STATUS_NO_MEM;
5513 
5514   /* check if we need to do dark calibration (shading) */
5515   if (BIT(calib_format.ability1, 2))
5516     {
5517       DBG (1, "normal_calibration: reading dark data\n");
5518       /* read dark calib data */
5519       status = get_calib_data (s, 0x66, calib_tmp_data, calib_data_size);
5520 
5521       if (status != SANE_STATUS_GOOD) {
5522 	free (calib_tmp_data);
5523 	return status;
5524       }
5525 
5526       /* process dark data: sort and average. */
5527 
5528       if (s->dark_avg_data) {
5529 	free (s->dark_avg_data);
5530 	s->dark_avg_data = 0;
5531       }
5532       s->dark_avg_data = sort_and_average (&calib_format, calib_tmp_data);
5533       if (!s->dark_avg_data) {
5534 	free (calib_tmp_data);
5535 	return SANE_STATUS_NO_MEM;
5536       }
5537       compute_dark_shading_data (s, &calib_format, s->dark_avg_data);
5538     }
5539 
5540   /* do we use a color mode? */
5541   if (calib_format.channels > 1) {
5542     DBG (3, "normal_calibration: using color calibration\n");
5543     read_type = 0x62; /* read color calib data */
5544   }
5545   else {
5546     DBG (3, "normal_calibration: using gray calibration\n");
5547     read_type = 0x61; /* gray calib data */
5548   }
5549 
5550   /* do white calibration: read gray or color data */
5551   status = get_calib_data (s, read_type, calib_tmp_data, calib_data_size);
5552 
5553   if (status != SANE_STATUS_GOOD) {
5554     free (calib_tmp_data);
5555     return status;
5556   }
5557 
5558   if (0) /* debug */
5559     {
5560       FILE* f = NULL;
5561       f = fopen ("calibration-white.pnm", "w");
5562       write_pnm_header (f, AV_GRAYSCALE, calib_format.bytes_per_channel * 8,
5563 			calib_format.pixel_per_line,
5564 			calib_format.lines * calib_format.channels);
5565 
5566       fwrite (calib_tmp_data, 1, calib_data_size, f);
5567       fclose (f);
5568     }
5569 
5570   if (s->white_avg_data) {
5571     free (s->white_avg_data);
5572     s->white_avg_data = 0;
5573   }
5574   s->white_avg_data = sort_and_average (&calib_format, calib_tmp_data);
5575   if (!s->white_avg_data) {
5576     free (calib_tmp_data);
5577     return SANE_STATUS_NO_MEM;
5578   }
5579 
5580   /* decrease white average data (if dark average data is present) */
5581   if (s->dark_avg_data) {
5582     int elements_per_line = calib_format.pixel_per_line * calib_format.channels;
5583     int i;
5584 
5585     DBG (1, "normal_calibration: dark data present - decreasing white average data\n");
5586 
5587     for (i = 0; i < elements_per_line; ++ i) {
5588       s->white_avg_data[i] -= s->dark_avg_data[i];
5589     }
5590   }
5591 
5592   compute_white_shading_data (s, &calib_format, s->white_avg_data);
5593 
5594   status = set_calib_data (s, &calib_format,
5595 			   s->dark_avg_data, s->white_avg_data);
5596 
5597   free (calib_tmp_data);
5598   return status;
5599 }
5600 
5601 /* next was taken from the GIMP and is a bit modified ... ;-)
5602  * original Copyright (C) 1995 Spencer Kimball and Peter Mattis
5603  */
5604 static double
brightness_contrast_func(double brightness,double contrast,double value)5605 brightness_contrast_func (double brightness, double contrast, double value)
5606 {
5607   double nvalue;
5608   double power;
5609 
5610   /* apply brightness */
5611   if (brightness < 0.0)
5612     value = value * (1.0 + brightness);
5613   else
5614     value = value + ((1.0 - value) * brightness);
5615 
5616   /* apply contrast */
5617   if (contrast < 0.0)
5618     {
5619       if (value > 0.5)
5620 	nvalue = 1.0 - value;
5621       else
5622 	nvalue = value;
5623       if (nvalue < 0.0)
5624 	nvalue = 0.0;
5625       nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + contrast));
5626       if (value > 0.5)
5627 	value = 1.0 - nvalue;
5628       else
5629 	value = nvalue;
5630     }
5631   else
5632     {
5633       if (value > 0.5)
5634 	nvalue = 1.0 - value;
5635       else
5636 	nvalue = value;
5637       if (nvalue < 0.0)
5638 	nvalue = 0.0;
5639       power = (contrast == 1.0) ? 127 : 1.0 / (1.0 - contrast);
5640       nvalue = 0.5 * pow (2.0 * nvalue, power);
5641       if (value > 0.5)
5642 	value = 1.0 - nvalue;
5643       else
5644 	value = nvalue;
5645     }
5646   return value;
5647 }
5648 
5649 static SANE_Status
send_gamma(Avision_Scanner * s)5650 send_gamma (Avision_Scanner* s)
5651 {
5652   Avision_Device* dev = s->hw;
5653   SANE_Status status = SANE_STATUS_GOOD;
5654 
5655   int invert_table = 0;
5656 
5657   size_t gamma_table_raw_size;
5658   size_t gamma_table_size;
5659   size_t gamma_values;
5660 
5661   struct command_send scmd;
5662   uint8_t *gamma_data;
5663 
5664   int color; /* current color */
5665   size_t i; /* big table index */
5666   size_t j; /* little table index */
5667   size_t k; /* big table sub index */
5668   double v1, v2;
5669 
5670   double brightness;
5671   double contrast;
5672 
5673   if (dev->inquiry_asic_type != AV_ASIC_OA980)
5674     invert_table = (s->c_mode == AV_THRESHOLDED) || (s->c_mode == AV_DITHERED);
5675 
5676   switch (dev->inquiry_asic_type)
5677     {
5678     case AV_ASIC_Cx:
5679     case AV_ASIC_C1:
5680       gamma_table_raw_size = 4096;
5681       gamma_table_size = 2048;
5682       break;
5683     case AV_ASIC_C5:
5684       gamma_table_raw_size = 256;
5685       gamma_table_size = 256;
5686       break;
5687       break;
5688     case AV_ASIC_OA980:
5689       gamma_table_raw_size = 4096;
5690       gamma_table_size = 4096;
5691       break;
5692     case AV_ASIC_OA982:
5693       gamma_table_raw_size = 256;
5694       gamma_table_size = 256;
5695       break;
5696     default:
5697       gamma_table_raw_size = 512; /* SPEC claims: 256 ... ? */
5698       gamma_table_size = 512;
5699     }
5700 
5701   gamma_values = gamma_table_size / 256;
5702 
5703   DBG (3, "send_gamma: table_raw_size: %lu, table_size: %lu\n",
5704        (u_long) gamma_table_raw_size, (u_long) gamma_table_size);
5705   DBG (3, "send_gamma: values: %lu, invert_table: %d\n",
5706        (u_long) gamma_values, invert_table);
5707 
5708   /* prepare for emulating contrast, brightness ... via the gamma-table */
5709   brightness = SANE_UNFIX (s->val[OPT_BRIGHTNESS].w);
5710   brightness /= 100;
5711   contrast = SANE_UNFIX (s->val[OPT_CONTRAST].w);
5712   contrast /= 100;
5713 
5714   DBG (3, "send_gamma: brightness: %f, contrast: %f\n", brightness, contrast);
5715 
5716   gamma_data = malloc (gamma_table_raw_size);
5717   if (!gamma_data)
5718     return SANE_STATUS_NO_MEM;
5719 
5720   memset (&scmd, 0, sizeof (scmd) );
5721 
5722   scmd.opc = AVISION_SCSI_SEND;
5723   scmd.datatypecode = 0x81; /* 0x81 for download gamma table */
5724   set_triple (scmd.transferlen, gamma_table_raw_size);
5725 
5726   for (color = 0; color < 3 && status == SANE_STATUS_GOOD; ++ color)
5727     {
5728       /* color: 0=red; 1=green; 2=blue */
5729       set_double (scmd.datatypequal, color);
5730 
5731       i = 0; /* big table index */
5732       for (j = 0; j < 256; ++ j) /* little table index */
5733 	{
5734 	  /* calculate mode dependent values v1 and v2
5735 	   * v1 <- current value for table
5736 	   * v2 <- next value for table (for interpolation)
5737 	   */
5738 	  switch (s->c_mode)
5739 	    {
5740 	    case AV_TRUECOLOR:
5741 	    case AV_TRUECOLOR12:
5742 	    case AV_TRUECOLOR16:
5743 	      {
5744 		v1 = (double) s->gamma_table [1 + color][j];
5745 		if (j == 255)
5746 		  v2 = (double) v1;
5747 		else
5748 		  v2 = (double) s->gamma_table [1 + color][j + 1];
5749 	      }
5750 	      break;
5751 	    default:
5752 	      /* for all other modes: */
5753 	      {
5754 		v1 = (double) s->gamma_table [0][j];
5755 		if (j == 255)
5756 		  v2 = (double) v1;
5757 		else
5758 		  v2 = (double) s->gamma_table [0][j + 1];
5759 	      }
5760 	    } /*end switch */
5761 
5762 	  /* Emulate brightness and contrast (at least the Avision AV6[2,3]0
5763 	   * as well as many others do not have a hardware implementation,
5764 	   * --$. The function was taken from the GIMP source - maybe I'll
5765 	   * optimize it in the future (when I have spare time). */
5766 
5767 	  v1 /= 255;
5768 	  v2 /= 255;
5769 
5770 	  v1 = (brightness_contrast_func (brightness, contrast, v1) );
5771 	  v2 = (brightness_contrast_func (brightness, contrast, v2) );
5772 
5773 	  v1 *= 255;
5774 	  v2 *= 255;
5775 
5776 	  if (invert_table) {
5777 	    v1 = 255 - v1;
5778 	    v2 = 255 - v2;
5779 	    if (v1 <= 0)
5780 	      v1 = 0;
5781 	    if (v2 <= 0)
5782 	      v2 = 0;
5783 	  }
5784 
5785           if (s->hw->hw->feature_type & AV_GAMMA_UINT16) {
5786             /* Use some pointer-cast magic to use gamma_data as uint16 array
5787                and write as big-endian since values get swapped */
5788             ((uint16_t *)gamma_data) [i++] = (uint16_t)v1<<8;
5789           } else {
5790             /* interpolate gamma_values to gamma_data */
5791 	    for (k = 0; k < gamma_values; ++ k, ++ i) {
5792 	      gamma_data [i] = (uint8_t)
5793 	        (((v1 * (gamma_values - k)) + (v2 * k) ) / (double) gamma_values);
5794 	    }
5795           }
5796 
5797 	}
5798 
5799       /* with AV_GAMMA_UINT16 only every second value is filled, so double i */
5800       if (s->hw->hw->feature_type & AV_GAMMA_UINT16)
5801         i *= 2;
5802 
5803       /* fill the gamma table - (e.g.) if 11bit (old protocol) table */
5804       {
5805 	size_t t_i = i-1;
5806 	if (i < gamma_table_raw_size) {
5807 	  DBG (4, "send_gamma: (old protocol) - filling the table.\n");
5808 	  for ( ; i < gamma_table_raw_size; ++ i)
5809 	    gamma_data [i] = gamma_data [t_i];
5810 	}
5811       }
5812 
5813       DBG (4, "send_gamma: sending %lu bytes gamma table.\n",
5814 	   (u_long) gamma_table_raw_size);
5815       status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5816 			    gamma_data, gamma_table_raw_size, 0, 0);
5817 
5818       if (status != SANE_STATUS_GOOD) {
5819 	DBG (1, "send_gamma: gamma table upload failed: %s\n",
5820 	     sane_strstatus (status));
5821       }
5822     }
5823   free (gamma_data);
5824   return status;
5825 }
5826 
5827 static SANE_Status
send_3x3_matrix(Avision_Scanner * s)5828 send_3x3_matrix (Avision_Scanner* s)
5829 {
5830   SANE_Status status;
5831 
5832 #define SIGN_BIT 0x1000
5833 #define INT_PART 10
5834 
5835   struct matrix_cmd
5836   {
5837     struct command_send scmd;
5838     struct matrix_3x3 matrix;
5839   } cmd;
5840 
5841   /* 04 00  00 00  00 00
5842      00 00  04 00  00 00
5843      00 00  00 00  04 00 */
5844 
5845   int i, a_i;
5846   static const double c5_matrix[] =
5847     { 1.000, 0.000, 0.000,
5848       0.000, 1.000, 0.000,
5849       0.000, 0.000, 1.000 };
5850 
5851   double a_f, b_f;
5852   uint16_t m;
5853 
5854   DBG (3, "send_3x3_matrix:\n");
5855 
5856   memset (&cmd, 0, sizeof (cmd));
5857 
5858   for (i = 0; i < 9; i++)
5859     {
5860       m = 0;
5861       a_f = c5_matrix[i];
5862       if (a_f < 0) {
5863 	m |= SIGN_BIT;
5864 	a_f = -a_f;
5865       }
5866 
5867       a_i = (int) a_f; /* integer */
5868       b_f = a_f - (double) a_i;  /* float */
5869       m |= ((a_i & 0x3) << INT_PART);
5870       m |= (uint16_t) (b_f * 1024);
5871       set_double (((uint8_t*)(&cmd.matrix.v[i])), m);
5872     }
5873 
5874   cmd.scmd.opc = AVISION_SCSI_SEND;
5875   cmd.scmd.datatypecode = 0x83; /* 0x83 for 3x3 color matrix */
5876   set_triple (cmd.scmd.transferlen, sizeof (struct matrix_3x3));
5877 
5878   if (1) {
5879     DBG (3, "send_3x3_matrix: sending matrix split into two commands\n");
5880     status = avision_cmd (&s->av_con, &cmd.scmd, sizeof (cmd.scmd),
5881                           &cmd.matrix, sizeof(cmd.matrix), 0, 0);
5882   }
5883   else {
5884     DBG (3, "send_3x3_matrix: sending matrix in one command\n");
5885     status = avision_cmd (&s->av_con, &cmd, sizeof (cmd), 0, 0, 0, 0);
5886   }
5887 
5888   return status;
5889 }
5890 
5891 static SANE_Status
get_acceleration_info(Avision_Scanner * s,struct acceleration_info * info)5892 get_acceleration_info (Avision_Scanner* s, struct acceleration_info* info)
5893 {
5894   SANE_Status status;
5895 
5896   struct command_read rcmd;
5897   uint8_t result [24];
5898   size_t size;
5899 
5900   DBG (3, "get_acceleration_info:\n");
5901 
5902   size = sizeof (result);
5903 
5904   memset (&rcmd, 0, sizeof (rcmd));
5905   rcmd.opc = AVISION_SCSI_READ;
5906   rcmd.datatypecode = 0x6c; /* get acceleration information */
5907   set_double (rcmd.datatypequal, s->hw->data_dq);
5908   set_triple (rcmd.transferlen, size);
5909 
5910   DBG (3, "get_acceleration_info: read_data: %lu bytes\n", (u_long) size);
5911   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
5912   if (status != SANE_STATUS_GOOD || size != sizeof (result) ) {
5913     DBG (1, "get_acceleration_info: read accel. info failed (%s)\n",
5914 	 sane_strstatus (status) );
5915     return status;
5916   }
5917 
5918   debug_print_accel_info (3, "get_acceleration_info", result);
5919 
5920   info->total_steps = get_double (&(result[0]));
5921   info->stable_steps = get_double (&(result[2]));
5922   info->table_units = get_quad (&(result[4]));
5923   info->base_units = get_quad (&(result[8]));
5924   info->start_speed = get_double (&(result[12]));
5925   info->target_speed = get_double (&(result[14]));
5926   info->ability = result[16];
5927   info->table_count = result[17];
5928 
5929   return SANE_STATUS_GOOD;
5930 }
5931 
5932 static SANE_Status
send_acceleration_table(Avision_Scanner * s)5933 send_acceleration_table (Avision_Scanner* s)
5934 {
5935   SANE_Status status;
5936 
5937   struct command_send scmd;
5938   int table = 0;
5939   int i;
5940   struct acceleration_info accel_info = accel_info;
5941   uint8_t* table_data;
5942 
5943   DBG (3, "send_acceleration_table:\n");
5944 
5945   do {
5946     status = get_acceleration_info (s, &accel_info);
5947 
5948     if (accel_info.table_count == 0) {
5949       DBG (3, "send_acceleration_table: device does not need tables\n");
5950       return SANE_STATUS_GOOD;
5951     }
5952 
5953     if (accel_info.target_speed > accel_info.start_speed ||
5954         accel_info.target_speed == 0 ||
5955         accel_info.total_steps <= accel_info.stable_steps) {
5956       DBG (1, "send_acceleration_table: table does not look right.\n");
5957       return SANE_STATUS_INVAL;
5958     }
5959 
5960     if (accel_info.ability != 0) {
5961       DBG (1, "send_acceleration_table: ability non-zero - insert code\n");
5962       return SANE_STATUS_INVAL;
5963     }
5964 
5965     /* so far I assume we have one byte tables as used in the C6 ASIC ... */
5966     table_data = malloc (accel_info.total_steps + 1000);
5967 
5968     memset (&scmd, 0x00, sizeof (scmd));
5969     scmd.opc = AVISION_SCSI_SEND;
5970     scmd.datatypecode = 0x6c; /* send acceleration table */
5971 
5972     set_double (scmd.datatypequal, table);
5973     set_triple (scmd.transferlen, accel_info.total_steps);
5974 
5975     /* construct the table - Warning: This code is derived from Avision
5976        sample code and is a bit scary! I have no idea why the scanner
5977        needs such a dumb table and also do not know /why/ it has to be
5978        constructed this way. "Works for me" -ReneR */
5979     {
5980       float low_lim = 0.001;
5981       float up_lim  = 1.0;
5982 
5983       uint16_t accel_steps = accel_info.total_steps - accel_info.stable_steps + 1;
5984 
5985       /* acceleration ramp */
5986       while ((up_lim - low_lim) > 0.0001)
5987       {
5988 	float mid = (up_lim + low_lim) / 2; /* accel rate */
5989 
5990 	uint16_t now_count = accel_info.start_speed;
5991 
5992 	uint16_t i = 0;
5993 
5994 	float now_count_f = now_count;
5995 	table_data [i++] = (uint8_t) accel_info.start_speed;
5996 
5997 	while (now_count != accel_info.target_speed)
5998 	  {
5999 	    now_count_f = now_count_f - (now_count_f -
6000 					 accel_info.target_speed) * mid;
6001 	    now_count = (uint16_t)(now_count_f + 0.5);
6002 	    table_data[i++] = (uint8_t) now_count;
6003 	  }
6004 
6005 
6006 	if (i == accel_steps)
6007 	  break;
6008 	if (i > accel_steps)
6009 	  low_lim = mid;
6010 	else
6011 	  up_lim = mid;
6012       }
6013 
6014       /* fill stable steps */
6015       for (i = accel_steps; i < accel_info.total_steps; i++)
6016 	  table_data [i] = table_data [i-1];
6017 
6018       debug_print_hex_raw (5, "send_acceleration_table: first pass:\n",
6019 			   table_data, accel_info.total_steps);
6020 
6021       /* maybe post fix-up */
6022       {
6023 	int add_count;
6024 
6025 	/* count total steps in table */
6026 	int table_total = 0;
6027 	for (i = 0; i < accel_info.total_steps; i++)
6028 	  table_total += table_data [i];
6029 
6030 	i = 0;
6031 	if (((table_total * accel_info.table_units) % accel_info.base_units) == 0)
6032 	  add_count = 0;
6033 	else
6034 	  add_count = (accel_info.base_units -
6035 		       ((table_total*accel_info.table_units) % accel_info.base_units))
6036 	    / accel_info.table_units;
6037 
6038 	/* add_count should not be bigger than 255 */
6039 	if (add_count > 255) {
6040 	  DBG (1, "send_acceleration_table: add_count limited, was: %d\n", add_count);
6041 	  add_count = 255;
6042 	}
6043 	for (i = 0; i < accel_info.total_steps - 1 && add_count > 0; i++)
6044 	  {
6045 	    uint16_t temp_count = 255 - table_data [i];
6046 	    temp_count = temp_count > add_count ? add_count : temp_count;
6047 
6048 	    table_data [i] += (uint8_t) temp_count;
6049 	    add_count -= temp_count;
6050 	  }
6051       }
6052     }
6053 
6054     debug_print_hex_raw (5, "send_acceleration_table: fixed up:\n",
6055 			 table_data, accel_info.total_steps);
6056 
6057     /* decrease all by one ... */
6058     for (i = 0; i < accel_info.total_steps; i++) {
6059       table_data[i]--;
6060     }
6061 
6062     DBG (1, "send_acceleration_table: sending table %d\n", table);
6063 
6064     debug_print_hex_raw (5, "send_acceleration_table: final:\n",
6065 			 table_data, accel_info.total_steps);
6066 
6067     status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
6068 			  (char*) table_data, accel_info.total_steps,
6069 			  0, 0);
6070     if (status != SANE_STATUS_GOOD) {
6071       DBG (3, "send_acceleration_table: send_data failed (%s)\n",
6072 	   sane_strstatus (status));
6073     }
6074 
6075     free (table_data); table_data = 0;
6076 
6077     table++;
6078   } while (table < accel_info.table_count);
6079 
6080 
6081   return status;
6082 }
6083 
6084 static SANE_Status
set_window(Avision_Scanner * s)6085 set_window (Avision_Scanner* s)
6086 {
6087   Avision_Device* dev = s->hw;
6088   SANE_Status status;
6089   int base_dpi_abs, base_dpi_rel;
6090   int transferlen;
6091   int paralen;
6092 
6093   int bytes_per_line;
6094   int line_count;
6095 
6096   struct {
6097     struct command_set_window cmd;
6098     struct command_set_window_window window;
6099   } cmd;
6100 
6101   DBG (1, "set_window:\n");
6102 
6103   /* plain old scanners, the C3 ASIC HP 53xx and the C6 ASIC HP 74xx
6104      and up do use 1200 as base - only the C5 differs */
6105   switch (dev->inquiry_asic_type) {
6106   case AV_ASIC_C5:
6107     base_dpi_abs = 1200;
6108     /* round down to the next multiple of 300 */
6109     base_dpi_rel = s->avdimen.hw_xres - s->avdimen.hw_xres % 300;
6110     if (base_dpi_rel > dev->inquiry_optical_res)
6111       base_dpi_rel = dev->inquiry_optical_res;
6112     else if (s->avdimen.hw_xres <= 150)
6113       base_dpi_rel = 150;
6114     break;
6115   default:
6116     base_dpi_abs = 1200;
6117     base_dpi_rel = 1200;
6118   }
6119 
6120   DBG (2, "set_window: base_dpi_abs: %d, base_dpi_rel: %d\n", base_dpi_abs, base_dpi_rel);
6121 
6122   /* wipe out anything */
6123   memset (&cmd, 0, sizeof (cmd) );
6124   cmd.window.descriptor.winid = AV_WINID; /* normally defined to be zero */
6125 
6126   /* optional parameter length to use */
6127   paralen = sizeof (cmd.window.avision) - sizeof (cmd.window.avision.type);
6128 
6129   DBG (2, "set_window: base paralen: %d\n", paralen);
6130 
6131   if (dev->hw->feature_type & AV_FUJITSU)
6132     paralen += sizeof (cmd.window.avision.type.fujitsu);
6133   else if (!dev->inquiry_new_protocol)
6134     paralen += sizeof (cmd.window.avision.type.old);
6135   else if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN)
6136     paralen += sizeof (cmd.window.avision.type.normal);
6137   else
6138     paralen += sizeof (cmd.window.avision.type.normal) - 1;
6139 
6140   DBG (2, "set_window: final paralen: %d\n", paralen);
6141 
6142   transferlen = sizeof (cmd.window)
6143     - sizeof (cmd.window.avision) + paralen;
6144 
6145   DBG (2, "set_window: transferlen: %d\n", transferlen);
6146 
6147   /* command setup */
6148   cmd.cmd.opc = AVISION_SCSI_SET_WINDOW;
6149   set_triple (cmd.cmd.transferlen, transferlen);
6150   set_double (cmd.window.header.desclen,
6151 	      sizeof (cmd.window.descriptor) + paralen);
6152 
6153   /* resolution parameters */
6154   set_double (cmd.window.descriptor.xres, s->avdimen.hw_xres);
6155   set_double (cmd.window.descriptor.yres, s->avdimen.hw_yres);
6156 
6157   /* upper left corner x/y as well as width/length in inch * base_dpi
6158      - avdimen are world pixels */
6159   set_quad (cmd.window.descriptor.ulx, s->avdimen.tlx * base_dpi_abs / s->avdimen.hw_xres);
6160   set_quad (cmd.window.descriptor.uly, s->avdimen.tly * base_dpi_abs / s->avdimen.hw_yres);
6161 
6162   set_quad (cmd.window.descriptor.width,
6163 	    s->avdimen.hw_pixels_per_line * base_dpi_rel / s->avdimen.hw_xres + 1);
6164   line_count = s->avdimen.hw_lines + 2 * s->avdimen.line_difference;
6165   set_quad (cmd.window.descriptor.length,
6166 	    line_count * base_dpi_rel / s->avdimen.hw_yres + 1);
6167 
6168   /* interlaced duplex scans are twice as long */
6169   if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) {
6170     DBG (2, "set_window: interlaced duplex scan, doubled line count\n");
6171     line_count *= 2;
6172   }
6173 
6174   bytes_per_line = s->avdimen.hw_bytes_per_line;
6175 
6176   set_double (cmd.window.avision.line_width, bytes_per_line);
6177   set_double (cmd.window.avision.line_count, line_count);
6178 
6179   /* here go the most significant bits if bigger than 16 bit */
6180   if (dev->inquiry_new_protocol && !(dev->hw->feature_type & AV_FUJITSU) ) {
6181     DBG (2, "set_window: large data-transfer support (>16bit)!\n");
6182     cmd.window.avision.type.normal.line_width_msb =
6183       bytes_per_line >> 16;
6184     cmd.window.avision.type.normal.line_count_msb =
6185       line_count >> 16;
6186   }
6187 
6188   if (dev->inquiry_background_raster)
6189     cmd.window.avision.type.normal.background_lines = s->val[OPT_BACKGROUND].w;
6190 
6191   /* scanner should use our line-width and count */
6192   SET_BIT (cmd.window.avision.bitset1, 6);
6193 
6194   /* set speed */
6195   cmd.window.avision.bitset1 |= s->val[OPT_SPEED].w & 0x07; /* only 3 bit */
6196 
6197   /* ADF scan? */
6198   DBG (3, "set_window: source mode %d source mode dim %d\n",
6199        s->source_mode, s->source_mode_dim);
6200 
6201   if (s->source_mode == AV_ADF ||
6202       s->source_mode == AV_ADF_REAR ||
6203       s->source_mode == AV_ADF_DUPLEX) {
6204     DBG (3, "set_window: filling ADF bits\n");
6205     SET_BIT (cmd.window.avision.bitset1, 7);
6206 
6207     if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN) {
6208       /* Always set bit 7 to enable single_sheet_scan option (defaults to off).
6209          This removes the 1s pause between two sheets and fixes some offsets. */
6210       SET_BIT(cmd.window.avision.type.normal.bitset3, 7);
6211       cmd.window.avision.type.normal.single_sheet_scan = 0;
6212     }
6213 
6214     /* normal, interlaced duplex scanners */
6215     if (dev->inquiry_duplex_interlaced) {
6216       DBG (3, "set_window: interlaced duplex type\n");
6217       if (s->source_mode == AV_ADF_REAR) {
6218         SET_BIT(cmd.window.avision.type.normal.bitset3, 3); /* 0x08 */
6219       }
6220       if (s->source_mode == AV_ADF_DUPLEX) {
6221         SET_BIT(cmd.window.avision.type.normal.bitset3, 4); /* 0x10 */
6222       }
6223     }
6224     else if (s->source_mode == AV_ADF_DUPLEX) /* HP 2-pass duplex */
6225     {
6226       DBG (3, "set_window: non-interlaced duplex type (HP)\n");
6227       SET_BIT(cmd.window.avision.type.normal.bitset3, 0); /* DPLX 0x01 */
6228       if (s->val[OPT_ADF_FLIP].w)
6229         SET_BIT(cmd.window.avision.type.normal.bitset3, 1); /* FLIP 0x02 */
6230       SET_BIT(cmd.window.avision.type.normal.bitset3, 2); /* MIRR 0x04 */
6231     }
6232   }
6233 
6234   if (s->val[OPT_PAPERLEN].w != SANE_FALSE) {
6235      set_double (cmd.window.descriptor.paper_length, (int)((double)30.0*1200));
6236   }
6237 
6238   if ( !(dev->hw->feature_type & AV_FUJITSU) )
6239     {
6240       /* quality scan option switch */
6241       if (s->val[OPT_QSCAN].w == SANE_TRUE &&
6242           !(dev->hw->feature_type & AV_NO_QSCAN_MODE)) {
6243 	SET_BIT (cmd.window.avision.type.normal.bitset2, 4);
6244       }
6245 
6246       /* quality calibration option switch (inverted! if set == speed) */
6247       if (s->val[OPT_QCALIB].w == SANE_FALSE &&
6248           !(dev->hw->feature_type & AV_NO_QCALIB_MODE)) {
6249 	SET_BIT (cmd.window.avision.type.normal.bitset2, 3);
6250       }
6251 
6252       /* transparency option switch */
6253       if (s->source_mode_dim == AV_TRANSPARENT_DIM) {
6254 	SET_BIT (cmd.window.avision.type.normal.bitset2, 7);
6255       }
6256 
6257       if (dev->scanner_type == AV_FILM) {
6258 	/* TODO: wire to IR exposure option? */
6259 	cmd.window.avision.type.normal.ir_exposure_time = 100;
6260 	set_double (cmd.window.avision.type.normal.r_exposure_time, s->val[OPT_EXPOSURE].w);
6261 	set_double (cmd.window.avision.type.normal.g_exposure_time, s->val[OPT_EXPOSURE].w);
6262 	set_double (cmd.window.avision.type.normal.b_exposure_time, s->val[OPT_EXPOSURE].w);
6263 
6264 	if (s->val[OPT_IR].w)
6265 	  cmd.window.avision.type.normal.bitset3 |= (1 << 0);
6266 
6267 	if (s->val[OPT_MULTISAMPLE].w)
6268 	  cmd.window.avision.type.normal.bitset3 |= (1 << 1);
6269       }
6270     }
6271 
6272   /* fixed values */
6273   cmd.window.descriptor.padding_and_bitset = 3;
6274   cmd.window.descriptor.vendor_specific = 0xFF;
6275   cmd.window.descriptor.paralen = paralen; /* R² was: 9, later 14 */
6276 
6277   /* This is normally unsupported by Avision scanners, and we do this
6278      via the gamma table - which works for all devices ... */
6279   cmd.window.descriptor.threshold = 128;
6280   cmd.window.descriptor.brightness = 128;
6281   cmd.window.descriptor.contrast = 128;
6282   cmd.window.avision.highlight = 0xFF;
6283   cmd.window.avision.shadow = 0x00;
6284 
6285   /* mode dependent settings */
6286   switch (s->c_mode)
6287     {
6288     case AV_THRESHOLDED:
6289       cmd.window.descriptor.bpc = 1;
6290       cmd.window.descriptor.image_comp = 0;
6291       break;
6292 
6293     case AV_DITHERED:
6294       cmd.window.descriptor.bpc = 1;
6295       cmd.window.descriptor.image_comp = 1;
6296       break;
6297 
6298     case AV_GRAYSCALE:
6299       cmd.window.descriptor.bpc = 8;
6300       cmd.window.descriptor.image_comp = 2;
6301       break;
6302 
6303     case AV_GRAYSCALE12:
6304       cmd.window.descriptor.bpc = 12;
6305       cmd.window.descriptor.image_comp = 2;
6306       break;
6307 
6308     case AV_GRAYSCALE16:
6309       cmd.window.descriptor.bpc = 16;
6310       cmd.window.descriptor.image_comp = 2;
6311       break;
6312 
6313     case AV_TRUECOLOR:
6314       cmd.window.descriptor.bpc = 8;
6315       cmd.window.descriptor.image_comp = 5;
6316       break;
6317 
6318     case AV_TRUECOLOR12:
6319       cmd.window.descriptor.bpc = 12;
6320       cmd.window.descriptor.image_comp = 5;
6321       break;
6322 
6323     case AV_TRUECOLOR16:
6324       cmd.window.descriptor.bpc = 16;
6325       cmd.window.descriptor.image_comp = 5;
6326       break;
6327 
6328     default:
6329       DBG (1, "Invalid mode. %d\n", s->c_mode);
6330       return SANE_STATUS_INVAL;
6331     }
6332 
6333   if (color_mode_is_color (s->c_mode)) {
6334     cmd.window.avision.bitset1 |= AVISION_FILTER_RGB;
6335   }
6336   else {
6337     if (dev->hw->feature_type & AV_FASTER_WITH_FILTER)
6338       cmd.window.avision.bitset1 |= AVISION_FILTER_GREEN;
6339     else if (dev->hw->feature_type & AV_USE_GRAY_FILTER)
6340       cmd.window.avision.bitset1 |= AVISION_FILTER_GRAY;
6341     else
6342       cmd.window.avision.bitset1 |= AVISION_FILTER_NONE;
6343   }
6344 
6345   debug_print_window_descriptor (5, "set_window", &(cmd.window));
6346 
6347   DBG (3, "set_window: sending command. Bytes: %d\n", transferlen);
6348   status = avision_cmd (&s->av_con, &cmd, sizeof (cmd.cmd),
6349 			&(cmd.window), transferlen, 0, 0);
6350 
6351   return status;
6352 }
6353 
6354 static SANE_Status
get_background_raster(Avision_Scanner * s)6355 get_background_raster (Avision_Scanner* s)
6356 {
6357   const int debug = 0;
6358 
6359   Avision_Device* dev = s->hw;
6360   SANE_Status status;
6361 
6362   struct command_read rcmd;
6363   size_t size;
6364   int bytes_per_line, i;
6365   const int bpp = color_mode_is_color (s->c_mode) ? 3 : 1;
6366   const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1);
6367 
6368   uint8_t* background = NULL;
6369 
6370   DBG (1, "get_background_raster:\n");
6371 
6372   if (lines == 0) {
6373     DBG (1, "get_background_raster: no background requested\n");
6374     return SANE_STATUS_GOOD;
6375   }
6376 
6377   /* full width, always :-(, duplex *2 for front and rear */
6378   bytes_per_line = dev->inquiry_background_raster_pixel *
6379     s->avdimen.hw_xres / dev->inquiry_optical_res;
6380   bytes_per_line *= bpp;
6381 
6382   DBG (3, "get_background_raster: native raster pixels: %d, raster bytes_per_line: %d\n",
6383        dev->inquiry_background_raster_pixel, bytes_per_line);
6384 
6385   /* according to spec only 8-bit gray or color, TODO: test for bi-level scans */
6386   size = bytes_per_line * lines;
6387 
6388   DBG (3, "get_background_raster: buffer size: %ld\n", (long)size);
6389 
6390   background = s->background_raster = realloc (s->background_raster, size);
6391   if (!background)
6392     return SANE_STATUS_NO_MEM;
6393 
6394   memset (&rcmd, 0, sizeof (rcmd));
6395   rcmd.opc = AVISION_SCSI_READ;
6396   rcmd.datatypecode = 0x9b; /* get background raster */
6397   set_double (rcmd.datatypequal, s->hw->data_dq);
6398 
6399   /* Ok, well - this part is very messy. The AV122 and DM152 appear to
6400      contain differently buggy ASICs. The only combination I found to
6401      at least get a correct front raster out of them is to read it
6402      line by line and then every second line appears to be valid front
6403      data, ... */
6404 
6405   /* read the raster data */
6406   for (i = 0; i < lines;)
6407     {
6408       uint8_t* dst_raster = background + bytes_per_line * i;
6409       /* read stripe by stripe, or all in one chunk */
6410       size_t this_read, read_size;
6411       int this_lines;
6412 
6413       if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) {
6414 	if (dev->hw->feature_type & AV_BACKGROUND_QUIRK)
6415 	  this_lines = 1;
6416 	else
6417 	  this_lines = lines;
6418       }
6419       else {
6420 	this_lines = s->val[OPT_BACKGROUND].w;
6421       }
6422       this_read = bytes_per_line * this_lines;
6423 
6424       DBG (3, "get_background_raster: line: %d, lines: %d, %lu bytes\n",
6425 	   i, this_lines, (u_long) this_read);
6426 
6427       set_triple (rcmd.transferlen, this_read);
6428 
6429       read_size = this_read;
6430       status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size);
6431       if (status != SANE_STATUS_GOOD || read_size != this_read) {
6432 	DBG (1, "get_background_raster: read raster failed (%s)\n",
6433 	     sane_strstatus (status) );
6434 	return status;
6435       }
6436 
6437       i += this_lines;
6438     }
6439 
6440   /* dump raw result while debugging */
6441   if (debug)
6442     {
6443       FILE* f = NULL;
6444       f = fopen ("background-raw.pnm", "w");
6445 
6446       write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6447 			bytes_per_line / bpp, lines);
6448 
6449       fwrite (background, 1, bytes_per_line * lines, f);
6450       fclose (f);
6451     }
6452 
6453   /* line-pack - move to unified processing flow, later */
6454   if (dev->inquiry_needs_line_pack)
6455     {
6456       /* TODO: add 16bit per sample code? */
6457       int l, p;
6458 
6459       uint8_t* tmp_data = malloc (bytes_per_line);
6460       for (l = 0; l < lines; ++l)
6461 	{
6462 	  uint8_t* out_data = tmp_data;
6463 	  uint8_t* r_ptr = background + (bytes_per_line * l);
6464 	  uint8_t* g_ptr = r_ptr + bytes_per_line / bpp;
6465 	  uint8_t* b_ptr = g_ptr + bytes_per_line / bpp;
6466 
6467 	  for (p = 0; p < bytes_per_line;) {
6468 	    out_data [p++] = *(r_ptr++);
6469 	    out_data [p++] = *(g_ptr++);
6470 	    out_data [p++] = *(b_ptr++);
6471 	  }
6472 
6473 	  memcpy (background + (bytes_per_line * l), tmp_data, bytes_per_line);
6474 	}
6475 
6476       free (tmp_data);
6477     } /* end line pack */
6478 
6479   /* deinterlace? */
6480   if (s->avdimen.interlaced_duplex && (dev->hw->feature_type & AV_2ND_LINE_INTERLACED))
6481     {
6482       uint8_t* deinterlaced = malloc (size * 2);
6483       if (!deinterlaced)
6484 	return SANE_STATUS_NO_MEM;
6485 
6486       for (i = 0; i < lines; ++i)
6487 	{
6488 	  int dst_i = i / 2 + (i % 2) * (lines / 2);
6489 	  uint8_t* dst_raster; /* just no C99 in SANE :-( */
6490 	  uint8_t* src_raster;
6491 
6492 	  /* for the quirky devices and some resolutions the interlacing differs */
6493 	  if ((dev->hw->feature_type & AV_BACKGROUND_QUIRK) && (s->avdimen.hw_xres >= 150))
6494 	    dst_i = i / 2 + ((i+1) % 2) * (lines / 2);
6495 
6496 	  dst_raster = deinterlaced + bytes_per_line * dst_i;
6497 	  src_raster = background + bytes_per_line * i;
6498 
6499 	  DBG(3, "get_background_raster: deinterlaced %d -> %d\n", i, dst_i);
6500 	  memcpy(dst_raster, src_raster, bytes_per_line);
6501 	}
6502 
6503       free (background);
6504       background = s->background_raster = deinterlaced;
6505     }
6506 
6507   /* dump raw result while debugging */
6508   for (i = 0; debug && i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i)
6509     {
6510     FILE* f = NULL;
6511     uint8_t* raster = background;
6512     if (i == 0) {
6513       f = fopen ("background.pnm", "w");
6514     }
6515     else {
6516       f = fopen ("background-rear.pnm", "w");
6517       raster += bytes_per_line * s->val[OPT_BACKGROUND].w;
6518     }
6519 
6520     write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6521 		      bytes_per_line / bpp, s->val[OPT_BACKGROUND].w);
6522 
6523     fwrite (raster, 1, bytes_per_line * s->val[OPT_BACKGROUND].w, f);
6524     fclose (f);
6525   }
6526 
6527   /* crop from full-width scanlines to scan window */
6528   {
6529     uint8_t *dst_ptr, *src_ptr;
6530     dst_ptr = background;
6531     src_ptr = background + s->avdimen.tlx * bpp;
6532     for (i = 0; i < lines; ++i)
6533       {
6534 	memmove (dst_ptr, src_ptr, s->avdimen.hw_bytes_per_line);
6535 	dst_ptr += s->avdimen.hw_bytes_per_line;
6536 	src_ptr += bytes_per_line;
6537       }
6538   }
6539 
6540   /* soft-scale - move to unified processing flow, later */
6541   if (s->avdimen.hw_xres != s->avdimen.xres)
6542     {
6543       const uint8_t* out_data = background;
6544       uint8_t* dst = background;
6545 
6546       int l;
6547       for (l = 0; l < lines; ++l)
6548 	{
6549 	  const int hwbpl = s->avdimen.hw_bytes_per_line;
6550 	  const int sy = l;
6551 
6552 	  int x;
6553 	  for (x = 0; x < s->params.pixels_per_line; ++x)
6554 	    {
6555 	      const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line;
6556 	      const int sx = (int)floor(bx);
6557 	      const int xdist = (int) ((bx - sx) * 256);
6558 	      const int sxx = sx + 1;
6559 
6560 	      switch (bpp) {
6561 	      case 1:
6562 		{
6563 		  uint8_t v =
6564 		    ( out_data [sy*hwbpl  + sx ] * (256-xdist) +
6565 		      out_data [sy*hwbpl  + sxx] * xdist
6566 		    ) / (256);
6567 		  *dst++ = v;
6568 		}
6569 		break;
6570 
6571 	      case 3:
6572 		{
6573 		  int c;
6574 		  for (c = 0; c < 3; ++c)
6575 		    {
6576 		      uint8_t v =
6577 			( out_data [sy*hwbpl  + sx*3  + c] * (256-xdist) +
6578 			  out_data [sy*hwbpl  + sxx*3 + c] * xdist
6579 			  ) / (256);
6580 		      *dst++ = v;
6581 		    }
6582 		}
6583 		break;
6584 	      }
6585 	    }
6586 	}
6587     }
6588 
6589   /* dump final result while debugging */
6590   if (debug) {
6591     for (i = 0; i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i)
6592       {
6593 	FILE* f = NULL;
6594 	uint8_t* raster = background;
6595 	if (i == 0) {
6596 	  f = fopen ("background-final.pnm", "w");
6597 	}
6598 	else {
6599 	  f = fopen ("background-final-rear.pnm", "w");
6600 	  raster += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w;
6601 	}
6602 
6603 	write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6604 			  s->params.bytes_per_line / bpp, s->val[OPT_BACKGROUND].w);
6605 
6606 	fwrite (raster, 1, s->params.bytes_per_line * s->val[OPT_BACKGROUND].w, f);
6607 	fclose (f);
6608       }
6609   }
6610 
6611   return SANE_STATUS_GOOD;
6612 }
6613 
6614 static SANE_Status
reserve_unit(Avision_Scanner * s)6615 reserve_unit (Avision_Scanner* s)
6616 {
6617   char cmd[] =
6618     {AVISION_SCSI_RESERVE_UNIT, 0, 0, 0, 0, 0};
6619   SANE_Status status;
6620 
6621   DBG (1, "reserve_unit:\n");
6622 
6623   status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0);
6624   return status;
6625 }
6626 
6627 static SANE_Status
release_unit(Avision_Scanner * s,int type)6628 release_unit (Avision_Scanner* s, int type)
6629 {
6630   char cmd[] =
6631     {AVISION_SCSI_RELEASE_UNIT, 0, 0, 0, 0, 0};
6632   SANE_Status status;
6633 
6634   DBG (1, "release unit: type: %d\n", type);
6635   cmd[5] = type; /* latest scanners also allow 1: release paper and 2: end job */
6636   status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0);
6637   return status;
6638 }
6639 
6640 /* Check if a sheet is present. */
6641 static SANE_Status
media_check(Avision_Scanner * s)6642 media_check (Avision_Scanner* s)
6643 {
6644   char cmd[] = {AVISION_SCSI_MEDIA_CHECK, 0, 0, 0, 1, 0}; /* 1, 4 */
6645   SANE_Status status;
6646   uint8_t result[1]; /* 4 */
6647   size_t size = sizeof(result);
6648 
6649   status = avision_cmd (&s->av_con, cmd, sizeof (cmd),
6650 			0, 0, result, &size);
6651 
6652   debug_print_raw (5, "media_check: result\n", result, size);
6653 
6654   if (status == SANE_STATUS_GOOD) {
6655     if (!(result[0] & 0x1))
6656       status = SANE_STATUS_NO_DOCS;
6657   }
6658 
6659   return status;
6660 }
6661 
6662 #if 0 /* unused */
6663 static SANE_Status
6664 flush_media (Avision_Scanner* s)
6665 {
6666   Avision_Device* dev = s->hw;
6667   SANE_Status status;
6668 
6669   if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_batch_scan)
6670     {
6671       DBG (1, "flush_media: flushing pages out of batch scanner\n");
6672       do {
6673 	status = media_check (s);
6674 	if (status == SANE_STATUS_GOOD) {
6675 	  SANE_Status status2 = reserve_unit (s);
6676 	  DBG (1, "flush_media: reserve status: %d\n", status2);
6677 	  status2 = release_unit (s, 0);
6678 	  DBG (1, "flush_media: release status: %d\n", status2);
6679 	}
6680       } while (status == SANE_STATUS_GOOD);
6681     }
6682   return SANE_STATUS_GOOD;
6683 }
6684 #endif /* 0 - unused */
6685 
6686 static SANE_Status
object_position(Avision_Scanner * s,uint8_t position)6687 object_position (Avision_Scanner* s, uint8_t position)
6688 {
6689   SANE_Status status;
6690 
6691   uint8_t cmd [10];
6692 
6693   memset (cmd, 0, sizeof (cmd));
6694   cmd[0] = AVISION_SCSI_OBJECT_POSITION;
6695   cmd[1] = position;
6696 
6697   DBG (1, "object_position: %d\n", position);
6698 
6699   status = avision_cmd (&s->av_con, cmd, sizeof(cmd), 0, 0, 0, 0);
6700   return status;
6701 }
6702 
6703 static SANE_Status
start_scan(Avision_Scanner * s)6704 start_scan (Avision_Scanner* s)
6705 {
6706   struct command_scan cmd;
6707 
6708   size_t size = sizeof (cmd);
6709 
6710   DBG (3, "start_scan:\n");
6711 
6712   memset (&cmd, 0, sizeof (cmd));
6713   cmd.opc = AVISION_SCSI_SCAN;
6714   cmd.transferlen = 1;
6715 
6716   /* AV610C2 in ADF preview mode does not detect the page end (...) */
6717   if (s->val[OPT_PREVIEW].w == SANE_TRUE && s->hw->inquiry_asic_type != AV_ASIC_C7) {
6718     SET_BIT(cmd.bitset1,6);
6719   }
6720 
6721   if (s->val[OPT_QSCAN].w == SANE_TRUE &&
6722       !(s->hw->hw->feature_type & AV_NO_QSCAN_MODE)) {
6723     SET_BIT(cmd.bitset1,7);
6724   }
6725 
6726   DBG (3, "start_scan: sending command. Bytes: %lu\n", (u_long) size);
6727   return avision_cmd (&s->av_con, &cmd, size, 0, 0, 0, 0);
6728 }
6729 
6730 static SANE_Status
do_eof(Avision_Scanner * s)6731 do_eof (Avision_Scanner *s)
6732 {
6733   int exit_status;
6734 
6735   DBG (3, "do_eof:\n");
6736 
6737   /* we do not scan anymore */
6738   s->prepared = s->scanning = SANE_FALSE;
6739 
6740   /* we can now mark the rear data as valid */
6741   if (s->avdimen.interlaced_duplex ||
6742       (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) {
6743     DBG (3, "do_eof: toggling duplex rear data valid\n");
6744     s->duplex_rear_valid = !s->duplex_rear_valid;
6745     DBG (3, "do_eof: duplex rear data valid: %x\n",
6746 	 s->duplex_rear_valid);
6747   }
6748 
6749   if (s->read_fds >= 0) {
6750     close (s->read_fds);
6751     s->read_fds = -1;
6752   }
6753 
6754   /* join our processes - without a wait() you will produce zombies
6755      (defunct children) */
6756   sanei_thread_waitpid (s->reader_pid, &exit_status);
6757   sanei_thread_invalidate (s->reader_pid);
6758 
6759   DBG (3, "do_eof: returning %d\n", exit_status);
6760   return (SANE_Status)exit_status;
6761 }
6762 
6763 static SANE_Status
do_cancel(Avision_Scanner * s)6764 do_cancel (Avision_Scanner* s)
6765 {
6766   int status;
6767 
6768   DBG (3, "do_cancel:\n");
6769 
6770   s->prepared = s->scanning = SANE_FALSE;
6771   s->duplex_rear_valid = SANE_FALSE;
6772   s->page = 0;
6773   s->cancelled = SANE_TRUE;
6774 
6775   if (s->read_fds >= 0) {
6776     close(s->read_fds);
6777     s->read_fds = -1;
6778   }
6779 
6780   if (sanei_thread_is_valid (s->reader_pid)) {
6781     int exit_status;
6782 
6783     /* ensure child knows it's time to stop: */
6784     sanei_thread_kill (s->reader_pid);
6785     sanei_thread_waitpid (s->reader_pid, &exit_status);
6786     sanei_thread_invalidate (s->reader_pid);
6787   }
6788 
6789   if (s->hw->hw->feature_type & AV_FASTFEED_ON_CANCEL) {
6790     status = release_unit (s, 1);
6791     if (status != SANE_STATUS_GOOD)
6792       DBG (1, "do_cancel: release_unit failed\n");
6793   }
6794 
6795   return SANE_STATUS_CANCELLED;
6796 }
6797 
6798 static SANE_Status
read_data(Avision_Scanner * s,SANE_Byte * buf,size_t * count)6799 read_data (Avision_Scanner* s, SANE_Byte* buf, size_t* count)
6800 {
6801   struct command_read rcmd;
6802   SANE_Status status;
6803 
6804   DBG (9, "read_data: %lu\n", (u_long) *count);
6805 
6806   memset (&rcmd, 0, sizeof (rcmd));
6807 
6808   rcmd.opc = AVISION_SCSI_READ;
6809   rcmd.datatypecode = 0x00; /* read image data */
6810   set_double (rcmd.datatypequal, s->hw->data_dq);
6811   set_triple (rcmd.transferlen, *count);
6812 
6813   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, buf, count);
6814 
6815   return status;
6816 }
6817 
6818 static SANE_Status
init_options(Avision_Scanner * s)6819 init_options (Avision_Scanner* s)
6820 {
6821   Avision_Device* dev = s->hw;
6822   int i;
6823 
6824   DBG (3, "init_options:\n");
6825 
6826   memset (s->opt, 0, sizeof (s->opt));
6827   memset (s->val, 0, sizeof (s->val));
6828 
6829   for (i = 0; i < NUM_OPTIONS; ++ i) {
6830     s->opt[i].size = sizeof (SANE_Word);
6831     s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
6832   }
6833 
6834   /* Init the SANE option from the scanner inquiry data */
6835 
6836   switch (dev->inquiry_asic_type) {
6837     case AV_ASIC_C2:
6838       dev->dpi_range.min = 100;
6839       break;
6840     case AV_ASIC_C5:
6841       dev->dpi_range.min = 80;
6842       break;
6843     case AV_ASIC_C6: /* TODO: AV610 in ADF mode does not scan less than 180 or so */
6844       dev->dpi_range.min = 50;
6845       break;
6846     case AV_ASIC_C7: /* AV610C2 empirically tested out */
6847       dev->dpi_range.min = 75;
6848       break;
6849     default:
6850       dev->dpi_range.min = 50;
6851   }
6852   DBG (1, "init_options: dpi_range.min set to %d\n", dev->dpi_range.min);
6853 
6854   dev->dpi_range.quant = 1; /* any, including 72, 144, etc. */
6855   dev->dpi_range.max = dev->inquiry_max_res;
6856 
6857   dev->speed_range.min = (SANE_Int)0;
6858   dev->speed_range.max = (SANE_Int)4;
6859   dev->speed_range.quant = (SANE_Int)1;
6860 
6861   s->opt[OPT_NUM_OPTS].name = "";
6862   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
6863   s->opt[OPT_NUM_OPTS].desc = "";
6864   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
6865   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
6866   s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT);
6867   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
6868 
6869   /* "Mode" group: */
6870   s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE;
6871   s->opt[OPT_MODE_GROUP].desc = ""; /* for groups only title and type are valid */
6872   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
6873   s->opt[OPT_MODE_GROUP].cap = 0;
6874   s->opt[OPT_MODE_GROUP].size = 0;
6875   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
6876 
6877   /* color mode */
6878   s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
6879   s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
6880   s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
6881   s->opt[OPT_MODE].type = SANE_TYPE_STRING;
6882   s->opt[OPT_MODE].size = max_string_size (dev->color_list);
6883   s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
6884   s->opt[OPT_MODE].constraint.string_list = dev->color_list;
6885   s->val[OPT_MODE].s = strdup (dev->color_list[dev->color_list_default]);
6886   s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s);
6887 
6888   /* source mode */
6889   s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
6890   s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
6891   s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
6892   s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
6893   s->opt[OPT_SOURCE].size = max_string_size(dev->source_list);
6894   s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
6895   s->opt[OPT_SOURCE].constraint.string_list = &dev->source_list[0];
6896   s->val[OPT_SOURCE].s = strdup(dev->source_list[0]);
6897   s->source_mode = match_source_mode (dev, s->val[OPT_SOURCE].s);
6898   s->source_mode_dim = match_source_mode_dim (s->source_mode);
6899 
6900   dev->x_range.max = SANE_FIX ( (int)dev->inquiry_x_ranges[s->source_mode_dim]);
6901   dev->x_range.quant = 0;
6902   dev->y_range.max = SANE_FIX ( (int)dev->inquiry_y_ranges[s->source_mode_dim]);
6903   dev->y_range.quant = 0;
6904 
6905   /* resolution */
6906   s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
6907   s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
6908   s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
6909   s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
6910   s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
6911   s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
6912   s->opt[OPT_RESOLUTION].constraint.range = &dev->dpi_range;
6913   s->val[OPT_RESOLUTION].w = OPT_RESOLUTION_DEFAULT;
6914 
6915   /* preview */
6916   s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
6917   s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
6918   s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
6919   s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
6920   s->val[OPT_PREVIEW].w = 0;
6921 
6922   /* speed option */
6923   s->opt[OPT_SPEED].name  = SANE_NAME_SCAN_SPEED;
6924   s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED;
6925   s->opt[OPT_SPEED].desc  = SANE_DESC_SCAN_SPEED;
6926   s->opt[OPT_SPEED].type  = SANE_TYPE_INT;
6927   s->opt[OPT_SPEED].constraint_type  = SANE_CONSTRAINT_RANGE;
6928   s->opt[OPT_SPEED].constraint.range = &dev->speed_range;
6929   s->val[OPT_SPEED].w = 0;
6930   if (dev->scanner_type == AV_SHEETFEED)
6931     s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE;
6932 
6933   /* "Geometry" group: */
6934   s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
6935   s->opt[OPT_GEOMETRY_GROUP].desc = ""; /* for groups only title and type are valid */
6936   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
6937   s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
6938   s->opt[OPT_GEOMETRY_GROUP].size = 0;
6939   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
6940 
6941   /* top-left x */
6942   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
6943   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
6944   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
6945   s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
6946   s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
6947   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
6948   s->opt[OPT_TL_X].constraint.range = &dev->x_range;
6949   s->val[OPT_TL_X].w = 0;
6950 
6951   /* top-left y */
6952   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
6953   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
6954   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
6955   s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
6956   s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
6957   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
6958   s->opt[OPT_TL_Y].constraint.range = &dev->y_range;
6959   s->val[OPT_TL_Y].w = 0;
6960 
6961   /* bottom-right x */
6962   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
6963   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
6964   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
6965   s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
6966   s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
6967   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
6968   s->opt[OPT_BR_X].constraint.range = &dev->x_range;
6969   s->val[OPT_BR_X].w = dev->x_range.max;
6970 
6971   /* bottom-right y */
6972   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
6973   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
6974   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
6975   s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
6976   s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
6977   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
6978   s->opt[OPT_BR_Y].constraint.range = &dev->y_range;
6979   s->val[OPT_BR_Y].w = dev->y_range.max;
6980 
6981   /* overscan top */
6982   s->opt[OPT_OVERSCAN_TOP].name = "overscan-top";
6983   s->opt[OPT_OVERSCAN_TOP].title = "Overscan top";
6984   s->opt[OPT_OVERSCAN_TOP].desc = "The top overscan controls the additional area to scan before the paper is detected.";
6985   s->opt[OPT_OVERSCAN_TOP].type = SANE_TYPE_FIXED;
6986   s->opt[OPT_OVERSCAN_TOP].unit = SANE_UNIT_MM;
6987   s->opt[OPT_OVERSCAN_TOP].constraint_type = SANE_CONSTRAINT_RANGE;
6988   s->opt[OPT_OVERSCAN_TOP].constraint.range = &overscan_range;
6989   s->val[OPT_OVERSCAN_TOP].w = SANE_FIX(0);
6990 
6991   /* overscan bottom */
6992   s->opt[OPT_OVERSCAN_BOTTOM].name = "overscan-bottom";
6993   s->opt[OPT_OVERSCAN_BOTTOM].title = "Overscan bottom";
6994   s->opt[OPT_OVERSCAN_BOTTOM].desc = "The bottom overscan controls the additional area to scan after the paper end is detected.";
6995   s->opt[OPT_OVERSCAN_BOTTOM].type = SANE_TYPE_FIXED;
6996   s->opt[OPT_OVERSCAN_BOTTOM].unit = SANE_UNIT_MM;
6997   s->opt[OPT_OVERSCAN_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE;
6998   s->opt[OPT_OVERSCAN_BOTTOM].constraint.range = &overscan_range;
6999   s->val[OPT_OVERSCAN_BOTTOM].w = SANE_FIX(0);
7000 
7001   if (!dev->inquiry_tune_scan_length)
7002     s->opt[OPT_OVERSCAN_TOP].cap |= SANE_CAP_INACTIVE;
7003   if (!dev->inquiry_tune_scan_length)
7004     s->opt[OPT_OVERSCAN_BOTTOM].cap |= SANE_CAP_INACTIVE;
7005 
7006   /* background raster */
7007   s->opt[OPT_BACKGROUND].name = "background-lines";
7008   s->opt[OPT_BACKGROUND].title = "Background raster lines";
7009   s->opt[OPT_BACKGROUND].desc = "The background raster controls the additional background lines to scan before the paper is feed through the scanner.";
7010   s->opt[OPT_BACKGROUND].type = SANE_TYPE_INT;
7011   s->opt[OPT_BACKGROUND].unit = SANE_UNIT_PIXEL;
7012   s->opt[OPT_BACKGROUND].constraint_type = SANE_CONSTRAINT_RANGE;
7013   s->opt[OPT_BACKGROUND].constraint.range = &background_range;
7014   s->val[OPT_BACKGROUND].w = 0;
7015 
7016   if (!dev->inquiry_background_raster) {
7017     s->opt[OPT_BACKGROUND].cap |= SANE_CAP_INACTIVE;
7018   }
7019 
7020   /* "Enhancement" group: */
7021   s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
7022   s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* for groups only title and type are valid */
7023   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
7024   s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
7025   s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
7026   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7027 
7028   /* brightness */
7029   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
7030   s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
7031   s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
7032   s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
7033   if (disable_gamma_table)
7034     s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
7035   s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
7036   s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
7037   s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range;
7038   s->val[OPT_BRIGHTNESS].w = SANE_FIX(0);
7039 
7040   /* contrast */
7041   s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
7042   s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
7043   s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
7044   s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED;
7045   if (disable_gamma_table)
7046     s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
7047   s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
7048   s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
7049   s->opt[OPT_CONTRAST].constraint.range = &percentage_range;
7050   s->val[OPT_CONTRAST].w = SANE_FIX(0);
7051 
7052   /* Quality Scan */
7053   s->opt[OPT_QSCAN].name   = "quality-scan";
7054   s->opt[OPT_QSCAN].title  = "Quality scan";
7055   s->opt[OPT_QSCAN].desc   = "Turn on quality scanning (slower but better).";
7056   s->opt[OPT_QSCAN].type   = SANE_TYPE_BOOL;
7057   s->opt[OPT_QSCAN].unit   = SANE_UNIT_NONE;
7058   s->val[OPT_QSCAN].w      = SANE_TRUE;
7059   if (dev->hw->feature_type & AV_NO_QSCAN_MODE)
7060     s->opt[OPT_QSCAN].cap |= SANE_CAP_INACTIVE;
7061 
7062   /* Quality Calibration */
7063   s->opt[OPT_QCALIB].name  = SANE_NAME_QUALITY_CAL;
7064   s->opt[OPT_QCALIB].title = SANE_TITLE_QUALITY_CAL;
7065   s->opt[OPT_QCALIB].desc  = SANE_DESC_QUALITY_CAL;
7066   s->opt[OPT_QCALIB].type  = SANE_TYPE_BOOL;
7067   s->opt[OPT_QCALIB].unit  = SANE_UNIT_NONE;
7068   s->val[OPT_QCALIB].w     = SANE_TRUE;
7069   if (dev->hw->feature_type & AV_NO_QCALIB_MODE)
7070     s->opt[OPT_QCALIB].cap |= SANE_CAP_INACTIVE;
7071 
7072   /* gray scale gamma vector */
7073   s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
7074   s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
7075   s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
7076   s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
7077   s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
7078   s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
7079   s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word);
7080   s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
7081   s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range;
7082   s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0];
7083 
7084   /* red gamma vector */
7085   s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
7086   s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
7087   s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
7088   s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
7089   s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
7090   s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
7091   s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word);
7092   s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
7093   s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
7094   s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0];
7095 
7096   /* green gamma vector */
7097   s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
7098   s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
7099   s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
7100   s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
7101   s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
7102   s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
7103   s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word);
7104   s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
7105   s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
7106   s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0];
7107 
7108   /* blue gamma vector */
7109   s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
7110   s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
7111   s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
7112   s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
7113   s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
7114   s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
7115   s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word);
7116   s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
7117   s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
7118   s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0];
7119 
7120   if (!disable_gamma_table)
7121   {
7122     if (color_mode_is_color (s->c_mode)) {
7123       s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
7124       s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
7125       s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
7126     }
7127     else {
7128       s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
7129     }
7130   }
7131 
7132   /* exposure */
7133   s->opt[OPT_EXPOSURE].name = "exposure";
7134   s->opt[OPT_EXPOSURE].title = "Exposure";
7135   s->opt[OPT_EXPOSURE].desc = "Manual exposure adjustment.";
7136   s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT;
7137   s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT;
7138   s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
7139   s->opt[OPT_EXPOSURE].constraint.range = &exposure_range;
7140   s->val[OPT_EXPOSURE].w = 100;
7141 
7142   if (!dev->inquiry_exposure_control) {
7143     s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
7144   }
7145 
7146   /* Multi sample */
7147   s->opt[OPT_MULTISAMPLE].name  = "multi-sample";
7148   s->opt[OPT_MULTISAMPLE].title = "Multi-sample";
7149   s->opt[OPT_MULTISAMPLE].desc  = "Enable multi-sample scan mode.";
7150   s->opt[OPT_MULTISAMPLE].type  = SANE_TYPE_BOOL;
7151   s->opt[OPT_MULTISAMPLE].unit  = SANE_UNIT_NONE;
7152   s->val[OPT_MULTISAMPLE].w     = SANE_FALSE;
7153 
7154   /* TODO: No idea how to detect, assume exposure control devices are
7155      new enough to support this, for now. -ReneR */
7156   if (!dev->inquiry_exposure_control) {
7157     s->opt[OPT_MULTISAMPLE].cap |= SANE_CAP_INACTIVE;
7158   }
7159 
7160   /* Infra-red */
7161   s->opt[OPT_IR].name  = "infra-red";
7162   s->opt[OPT_IR].title = "Infra-red";
7163   s->opt[OPT_IR].desc  = "Enable infra-red scan mode.";
7164   s->opt[OPT_IR].type  = SANE_TYPE_BOOL;
7165   s->opt[OPT_IR].unit  = SANE_UNIT_NONE;
7166   s->val[OPT_IR].w     = SANE_FALSE;
7167 
7168   /* TODO: No idea how to detect, assume exposure control devices are
7169      new enough to support this, for now. -ReneR */
7170   if (!dev->inquiry_exposure_control) {
7171     s->opt[OPT_IR].cap |= SANE_CAP_INACTIVE;
7172   }
7173 
7174   /* "MISC" group: */
7175   s->opt[OPT_MISC_GROUP].title = SANE_TITLE_SCAN_MODE;
7176   s->opt[OPT_MISC_GROUP].desc = ""; /* for groups only title and type are valid */
7177   s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP;
7178   s->opt[OPT_MISC_GROUP].cap = 0;
7179   s->opt[OPT_MISC_GROUP].size = 0;
7180   s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7181 
7182   /* film holder control */
7183   if (dev->scanner_type != AV_FILM)
7184     s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE;
7185   s->opt[OPT_FRAME].name = SANE_NAME_FRAME;
7186   s->opt[OPT_FRAME].title = SANE_TITLE_FRAME;
7187   s->opt[OPT_FRAME].desc = SANE_DESC_FRAME;
7188   s->opt[OPT_FRAME].type = SANE_TYPE_INT;
7189   s->opt[OPT_FRAME].unit = SANE_UNIT_NONE;
7190   s->opt[OPT_FRAME].constraint_type = SANE_CONSTRAINT_RANGE;
7191   s->opt[OPT_FRAME].constraint.range = &dev->frame_range;
7192   s->val[OPT_FRAME].w = dev->current_frame;
7193 
7194   /* power save time */
7195   if (!dev->inquiry_power_save_time)
7196     s->opt[OPT_POWER_SAVE_TIME].cap |= SANE_CAP_INACTIVE;
7197   s->opt[OPT_POWER_SAVE_TIME].name = "power-save-time";
7198   s->opt[OPT_POWER_SAVE_TIME].title = "Power save timer control";
7199   s->opt[OPT_POWER_SAVE_TIME].desc = "Allows control of the scanner's power save timer, dimming or turning off the light.";
7200   s->opt[OPT_POWER_SAVE_TIME].type = SANE_TYPE_INT;
7201   s->opt[OPT_POWER_SAVE_TIME].unit = SANE_UNIT_NONE;
7202   s->opt[OPT_POWER_SAVE_TIME].constraint_type = SANE_CONSTRAINT_NONE;
7203   s->val[OPT_POWER_SAVE_TIME].w = 0;
7204 
7205   /* message, like options set on the scanner, LED no. & co */
7206   s->opt[OPT_MESSAGE].name = "message";
7207   s->opt[OPT_MESSAGE].title = "message text from the scanner";
7208   s->opt[OPT_MESSAGE].desc = "This text contains device specific options controlled by the user on the scanner hardware.";
7209   s->opt[OPT_MESSAGE].type = SANE_TYPE_STRING;
7210   s->opt[OPT_MESSAGE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7211   s->opt[OPT_MESSAGE].size = 129;
7212   s->opt[OPT_MESSAGE].constraint_type = SANE_CONSTRAINT_NONE;
7213   s->val[OPT_MESSAGE].s = malloc(s->opt[OPT_MESSAGE].size);
7214   s->val[OPT_MESSAGE].s[0] = 0;
7215 
7216   /* NVRAM */
7217   s->opt[OPT_NVRAM].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7218   if (!dev->inquiry_nvram_read)
7219     s->opt[OPT_NVRAM].cap |= SANE_CAP_INACTIVE;
7220   s->opt[OPT_NVRAM].name = "nvram-values";
7221   s->opt[OPT_NVRAM].title = "Obtain NVRAM values";
7222   s->opt[OPT_NVRAM].desc = "Allows access obtaining the scanner's NVRAM values as pretty printed text.";
7223   s->opt[OPT_NVRAM].type = SANE_TYPE_STRING;
7224   s->opt[OPT_NVRAM].unit = SANE_UNIT_NONE;
7225   s->opt[OPT_NVRAM].size = 1024;
7226   s->opt[OPT_NVRAM].constraint_type = SANE_CONSTRAINT_NONE;
7227   s->val[OPT_NVRAM].s = malloc(s->opt[OPT_NVRAM].size);
7228   s->val[OPT_NVRAM].s[0] = 0;
7229 
7230   /* paper_length */
7231   s->opt[OPT_PAPERLEN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7232   if (!dev->inquiry_paper_length)
7233     s->opt[OPT_PAPERLEN].cap |= SANE_CAP_INACTIVE;
7234   s->opt[OPT_PAPERLEN].name  = "paper-length";
7235   s->opt[OPT_PAPERLEN].title = "Use paper length";
7236   s->opt[OPT_PAPERLEN].desc  = "Newer scanners can utilize this paper length to detect double feeds.  However some others (DM152) can get confused during media flush if it is set.";
7237   s->opt[OPT_PAPERLEN].type  = SANE_TYPE_BOOL;
7238   s->opt[OPT_PAPERLEN].unit  = SANE_UNIT_NONE;
7239   s->opt[OPT_PAPERLEN].size = sizeof(SANE_Word);
7240   s->opt[OPT_PAPERLEN].constraint_type = SANE_CONSTRAINT_NONE;
7241   s->val[OPT_PAPERLEN].w     = SANE_FALSE;
7242 
7243   /* ADF page flipping */
7244   s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
7245   if (!(s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX))
7246     s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
7247   s->opt[OPT_ADF_FLIP].name = "flip-page";
7248   s->opt[OPT_ADF_FLIP].title = "Flip document after duplex scanning";
7249   s->opt[OPT_ADF_FLIP].desc = "Tells page-flipping document scanners to flip the paper back to its original orientation before dropping it in the output tray.  Turning this off might make scanning a little faster if you don't care about manually flipping the pages afterwards.";
7250   s->opt[OPT_ADF_FLIP].type = SANE_TYPE_BOOL;
7251   s->opt[OPT_ADF_FLIP].unit = SANE_UNIT_NONE;
7252   s->opt[OPT_ADF_FLIP].size = sizeof(SANE_Word);
7253   s->opt[OPT_ADF_FLIP].constraint_type = SANE_CONSTRAINT_NONE;
7254   s->val[OPT_ADF_FLIP].w = SANE_TRUE;
7255 
7256   return SANE_STATUS_GOOD;
7257 }
7258 
7259 /* This function is executed as a child process. The reason this is
7260    executed as a subprocess is because some (most?) generic SCSI
7261    interfaces block a SCSI request until it has completed. With a
7262    subprocess, we can let it block waiting for the request to finish
7263    while the main process can go about to do more important things
7264    (such as recognizing when the user presses a cancel button).
7265 
7266    WARNING: Since this is executed as a subprocess, it's NOT possible
7267    to update any of the variables in the main process (in particular
7268    the scanner state cannot be updated).  */
7269 
7270 static int
reader_process(void * data)7271 reader_process (void *data)
7272 {
7273   struct Avision_Scanner *s = (struct Avision_Scanner *) data;
7274   int fd = s->write_fds;
7275 
7276   Avision_Device* dev = s->hw;
7277 
7278   SANE_Status status;
7279   SANE_Status exit_status = SANE_STATUS_GOOD;
7280   sigset_t sigterm_set;
7281   sigset_t ignore_set;
7282   struct SIGACTION act;
7283   int old;
7284 
7285   FILE* fp;
7286   FILE* fp_fd = 0; /* for ADF bottom offset truncating */
7287   FILE* rear_fp = 0; /* used to store the deinterlaced rear data */
7288   FILE* raw_fp = 0; /* used to write the RAW image data for debugging */
7289 
7290   /* the complex params */
7291   unsigned int lines_per_stripe;
7292   unsigned int lines_per_output;
7293   unsigned int max_bytes_per_read;
7294 
7295   SANE_Bool gray_mode;
7296 
7297   /* the simple params for the data reader */
7298   int hw_line = 0;
7299   int line = 0;
7300 
7301   unsigned int stripe_size;
7302   unsigned int stripe_fill;
7303   unsigned int out_size;
7304 
7305   size_t total_size;
7306   size_t processed_bytes;
7307 
7308   enum {
7309     NONE,   /* do not de-interlace at all */
7310     STRIPE, /* every 2nd stripe */
7311     HALF,   /* the 2nd half */
7312     LINE    /* every 2nd line */
7313   } deinterlace = NONE;
7314 
7315   /* the fat strip we currently puzzle together to perform software-colorpack
7316      and more */
7317   uint8_t* stripe_data;
7318   /* the corrected output data */
7319   uint8_t* out_data;
7320   /* interpolation output data, one line */
7321   uint8_t* ip_history = 0;
7322   uint8_t* ip_data = 0;
7323 
7324   DBG (3, "reader_process:\n");
7325 
7326   if (sanei_thread_is_forked()) {
7327     close (s->read_fds);
7328     s->read_fds = -1;
7329 
7330     sigfillset (&ignore_set);
7331     sigdelset (&ignore_set, SIGTERM);
7332 #if defined (__APPLE__) && defined (__MACH__)
7333     sigdelset (&ignore_set, SIGUSR2);
7334 #endif
7335     sigprocmask (SIG_SETMASK, &ignore_set, 0);
7336 
7337     memset (&act, 0, sizeof (act));
7338     sigaction (SIGTERM, &act, 0);
7339 
7340     sigemptyset (&sigterm_set);
7341     sigaddset (&sigterm_set, SIGTERM);
7342   }
7343 #ifdef USE_PTHREAD
7344   else {
7345     int old;
7346     pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
7347     pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
7348   }
7349 #endif
7350 
7351   gray_mode = color_mode_is_shaded (s->c_mode);
7352 
7353   if (s->avdimen.interlaced_duplex) {
7354     deinterlace = STRIPE;
7355 
7356     if ( (dev->hw->feature_type & AV_NON_INTERLACED_DUPLEX_300) &&
7357 	 (s->avdimen.hw_xres <= 300 && s->avdimen.hw_yres <= 300) )
7358       deinterlace = HALF;
7359     if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED)
7360       deinterlace = LINE;
7361 
7362     if (dev->scanner_type == AV_FILM)
7363       deinterlace = LINE;
7364   }
7365 
7366   fp = fdopen (fd, "w");
7367   if (!fp)
7368     return SANE_STATUS_NO_MEM;
7369 
7370   if (dev->adf_offset_compensation) {
7371     DBG (3, "reader_process: redirecting output data to temp file for ADF offset compensation.\n");
7372     fp_fd = fp;
7373     fp = fopen (s->duplex_offtmp_fname, "w+");
7374     if (!fp) {
7375       fclose(fp_fd);
7376       return SANE_STATUS_NO_MEM;
7377     }
7378   }
7379 
7380   /* start scan ? */
7381   if ((deinterlace == NONE && !((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->duplex_rear_valid)) ||
7382       (deinterlace != NONE && !s->duplex_rear_valid))
7383     {
7384       /* reserve unit - in the past we did this in open - but the
7385 	 windows driver does reserves for each scan and some ADF
7386 	 devices need a release for each sheet anyway ... */
7387       status = reserve_unit (s);
7388       if (status != SANE_STATUS_GOOD) {
7389 	DBG (1, "reader_process: reserve_unit failed: %s\n",
7390 	     sane_strstatus (status));
7391 	return status;
7392       }
7393 
7394       if (dev->hw->feature_type & AV_NO_START_SCAN) {
7395 	DBG (1, "reader_process: start_scan skipped due to device-list!\n");
7396       }
7397       else {
7398 	status = start_scan (s);
7399 	if (status != SANE_STATUS_GOOD) {
7400 	  DBG (1, "reader_process: start_scan failed: %s\n",
7401 	       sane_strstatus (status));
7402 	  return status;
7403 	}
7404       }
7405 
7406       if (dev->hw->feature_type & AV_ACCEL_TABLE)
7407      /*  (s->hw->inquiry_asic_type == AV_ASIC_C6) */ {
7408 	status = send_acceleration_table (s);
7409 	if (status != SANE_STATUS_GOOD) {
7410 	  DBG (1, "reader_process: send_acceleration_table failed: %s\n",
7411 	       sane_strstatus (status));
7412 	  return status;
7413 	}
7414       }
7415     }
7416 
7417   /* setup file i/o for deinterlacing scans or if we are the back page with a flipping duplexer */
7418   if (deinterlace != NONE ||
7419      (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2)))
7420     {
7421       if (!s->duplex_rear_valid) { /* create new file for writing */
7422 	DBG (3, "reader_process: opening duplex rear file for writing.\n");
7423 	rear_fp = fopen (s->duplex_rear_fname, "w");
7424 	if (! rear_fp) {
7425 	  fclose (fp);
7426 	  return SANE_STATUS_NO_MEM;
7427 	}
7428       }
7429       else { /* open saved rear data */
7430 	DBG (3, "reader_process: opening duplex rear file for reading.\n");
7431 	rear_fp = fopen (s->duplex_rear_fname, "r");
7432 	if (! rear_fp) {
7433 	  fclose (fp);
7434 	  return SANE_STATUS_IO_ERROR;
7435 	}
7436       }
7437     }
7438 
7439   /* it takes quite a few lines to saturate the (USB) bus */
7440   lines_per_stripe = dev->read_stripe_size;
7441   if (s->avdimen.line_difference)
7442     lines_per_stripe += 2 * s->avdimen.line_difference;
7443 
7444   stripe_size = s->avdimen.hw_bytes_per_line * lines_per_stripe;
7445   lines_per_output = lines_per_stripe - 2 * s->avdimen.line_difference;
7446 
7447   if (s->av_con.connection_type == AV_SCSI)
7448     /* maybe better not /2 ... */
7449     max_bytes_per_read = dev->scsi_buffer_size / 2;
7450   else
7451     /* vast buffer size to saturate the bus */
7452     max_bytes_per_read = 0x100000;
7453 
7454   out_size = s->avdimen.hw_bytes_per_line * lines_per_output;
7455 
7456   DBG (3, "dev->scsi_buffer_size / 2: %d\n",
7457        dev->scsi_buffer_size / 2);
7458 
7459   DBG (3, "bytes_per_line: %d, pixels_per_line: %d\n",
7460        s->avdimen.hw_bytes_per_line, s->avdimen.hw_pixels_per_line);
7461 
7462   DBG (3, "lines_per_stripe: %d, lines_per_output: %d\n",
7463        lines_per_stripe, lines_per_output);
7464 
7465   DBG (3, "max_bytes_per_read: %d, stripe_size: %d, out_size: %d\n",
7466        max_bytes_per_read, stripe_size, out_size);
7467 
7468   stripe_data = malloc (stripe_size);
7469 
7470   /* for software scaling we need an additional interpolation line buffer */
7471   if (s->avdimen.hw_xres != s->avdimen.xres ||
7472       s->avdimen.hw_yres != s->avdimen.yres)
7473   {
7474     /* layout out_data so that the interpolation history is exactly in front */
7475     ip_history = malloc (s->avdimen.hw_bytes_per_line + out_size);
7476     out_data = ip_history + s->avdimen.hw_bytes_per_line;
7477 
7478     ip_data = malloc (s->params.bytes_per_line);
7479   }
7480   else {
7481     out_data = malloc (out_size);
7482   }
7483 
7484   /* calculate params for the reading loop */
7485   total_size = s->avdimen.hw_bytes_per_line *
7486                (s->avdimen.hw_lines + 2 * s->avdimen.line_difference);
7487 
7488   if (deinterlace != NONE && !s->duplex_rear_valid)
7489     total_size *= 2;
7490   DBG (3, "reader_process: total_size: %lu\n", (u_long) total_size);
7491 
7492   /* write a RAW PNM file for debugging -ReneR */
7493   if (0 /* DEBUG */ &&
7494       (deinterlace == NONE || (deinterlace != NONE && !s->duplex_rear_valid)) )
7495     {
7496       raw_fp = fopen ("/tmp/sane-avision.raw", "w");
7497       write_pnm_header (fp, s->c_mode, s->params.depth,
7498 			s->avdimen.hw_pixels_per_line, total_size / s->avdimen.hw_bytes_per_line);
7499     }
7500 
7501   processed_bytes = 0;
7502   stripe_fill = 0;
7503 
7504   /* First, dump background raster, bypassing all the other processing. */
7505   if (dev->inquiry_background_raster && s->val[OPT_BACKGROUND].w)
7506     {
7507       uint8_t* background = s->background_raster;
7508       if (s->duplex_rear_valid)
7509 	background += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w;
7510 
7511       DBG (5, "reader_process: dumping background raster\n");
7512       fwrite (background, s->params.bytes_per_line, s->val[OPT_BACKGROUND].w, fp);
7513     }
7514 
7515   /* Data read; loop until all data has been processed.  Might exit
7516      before all lines are transferred for ADF paper end. */
7517   while (exit_status == SANE_STATUS_GOOD && processed_bytes < total_size)
7518     {
7519       unsigned int useful_bytes;
7520 
7521       DBG (5, "reader_process: stripe filled: %d\n", stripe_fill);
7522 
7523       /* fill the stripe buffer with real data */
7524       while (!s->duplex_rear_valid &&
7525 	     processed_bytes < total_size && stripe_fill < stripe_size &&
7526              exit_status  == SANE_STATUS_GOOD)
7527 	{
7528 	  size_t this_read = stripe_size - stripe_fill;
7529 
7530 	  /* Limit reads to max_bytes_per_read and global data
7531 	     boundaries. Rounded to the next lower multiple of
7532 	     byte_per_lines, otherwise some scanners freeze. */
7533 	  if (this_read > max_bytes_per_read)
7534 	    this_read = (max_bytes_per_read -
7535 			 max_bytes_per_read % s->avdimen.hw_bytes_per_line);
7536 
7537 	  if (processed_bytes + this_read > total_size)
7538 	    this_read = total_size - processed_bytes;
7539 
7540           read_constrains(s, this_read);
7541 
7542 	  DBG (5, "reader_process: processed_bytes: %lu, total_size: %lu\n",
7543 	       (u_long) processed_bytes, (u_long) total_size);
7544 	  DBG (5, "reader_process: this_read: %lu\n", (u_long) this_read);
7545 
7546 	  if (sanei_thread_is_forked())
7547 	    sigprocmask (SIG_BLOCK, &sigterm_set, 0);
7548 #ifdef USE_PTHREAD
7549 	  else
7550 	    pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
7551 #endif
7552 
7553 	  status = read_data (s, stripe_data + stripe_fill, &this_read);
7554 
7555 	  if (sanei_thread_is_forked())
7556 	    sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
7557 #ifdef USE_PTHREAD
7558 	  else
7559 	    pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
7560 #endif
7561 
7562 
7563 	  /* only EOF on the second stripe, as otherwise the rear page
7564 	     is shorter */
7565 	  if (status == SANE_STATUS_EOF && deinterlace == STRIPE) {
7566 	    if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980) {
7567 	      this_read = 0;
7568 	    } else {
7569 	      static int already_eof = 0;
7570 	      if (!already_eof) {
7571 		DBG (5, "reader_process: first EOF on stripe interlace: hiding.\n");
7572 		status = SANE_STATUS_GOOD;
7573 		already_eof = 1;
7574 	      }
7575 	    }
7576 	  }
7577 
7578 	  /* write RAW data to file for debugging */
7579 	  if (raw_fp && this_read > 0)
7580 	    fwrite (stripe_data + stripe_fill, this_read, 1, raw_fp);
7581 
7582 	  if (status == SANE_STATUS_EOF || this_read == 0) {
7583 	    DBG (1, "reader_process: read_data failed due to EOF\n");
7584 	    exit_status = SANE_STATUS_EOF;
7585 	  }
7586 
7587 	  if (status != SANE_STATUS_GOOD) {
7588 	    DBG (1, "reader_process: read_data failed with status: %d\n",
7589 		 status);
7590 	    exit_status = status;
7591 	  }
7592 
7593 	  stripe_fill += this_read;
7594 	  processed_bytes += this_read;
7595 	}
7596 
7597       /* fill the stripe buffer with stored, virtual data */
7598       if (s->duplex_rear_valid)
7599 	{
7600 	  size_t this_read = stripe_size - stripe_fill;
7601 	  size_t got;
7602 
7603 	  /* limit reads to max_read and global data boundaries */
7604 	  if (this_read > max_bytes_per_read)
7605 	    this_read = max_bytes_per_read;
7606 
7607 	  if (processed_bytes + this_read > total_size)
7608 	    this_read = total_size - processed_bytes;
7609 
7610 	  DBG (5, "reader_process: virtual processed_bytes: %lu, total_size: %lu\n",
7611 	       (u_long) processed_bytes, (u_long) total_size);
7612 	  DBG (5, "reader_process: virtual this_read: %lu\n", (u_long) this_read);
7613 
7614 	  got = fread (stripe_data + stripe_fill, 1, this_read, rear_fp);
7615 	  stripe_fill += got;
7616 	  processed_bytes += got;
7617 	  if (got != this_read)
7618 	    exit_status = SANE_STATUS_EOF;
7619 	}
7620 
7621       DBG (5, "reader_process: stripe filled: %d\n", stripe_fill);
7622 
7623       useful_bytes = stripe_fill;
7624 
7625       if (color_mode_is_color (s->c_mode))
7626 	useful_bytes -= 2 * s->avdimen.line_difference * s->avdimen.hw_bytes_per_line;
7627 
7628       DBG (3, "reader_process: useful_bytes %i\n", useful_bytes);
7629 
7630       /* Deinterlace, save the rear stripes. For some scanners (AV220)
7631 	 that is every 2nd stripe, the 2nd half of the transferred
7632 	 data ((AV83xx), or every 2nd line (AV122)). */
7633       if (deinterlace != NONE && !s->duplex_rear_valid)
7634 	{
7635 	  /* for all lines we have in the buffer: */
7636 	  unsigned int absline = (processed_bytes - stripe_fill) / s->avdimen.hw_bytes_per_line;
7637 	  unsigned int abslines = absline + useful_bytes / s->avdimen.hw_bytes_per_line;
7638 	  uint8_t* ptr = stripe_data;
7639 	  for ( ; absline < abslines; ++absline)
7640 	    {
7641 	      DBG (9, "reader_process: deinterlacing line %d\n", absline);
7642 	      /* interlaced? save the back data to the rear buffer */
7643 	      if ( (deinterlace == STRIPE && absline % (lines_per_stripe*2) >= lines_per_stripe) ||
7644 		   (deinterlace == HALF   && absline >= total_size / s->avdimen.hw_bytes_per_line / 2) ||
7645 		   (deinterlace == LINE   && (absline & 0x1)) ) /* last bit equals % 2 */
7646 		{
7647 		  DBG (9, "reader_process: saving rear line %d to temporary file.\n", absline);
7648 		  fwrite (ptr, s->avdimen.hw_bytes_per_line, 1, rear_fp);
7649 		  if (deinterlace == LINE)
7650 		    memmove (ptr, ptr+s->avdimen.hw_bytes_per_line,
7651 			     stripe_data + stripe_fill - ptr - s->avdimen.hw_bytes_per_line);
7652 		  else
7653 		    ptr += s->avdimen.hw_bytes_per_line;
7654 		  useful_bytes -= s->avdimen.hw_bytes_per_line;
7655 		  stripe_fill -= s->avdimen.hw_bytes_per_line;
7656 		}
7657 	      else
7658 		ptr += s->avdimen.hw_bytes_per_line;
7659  	    }
7660 	  DBG (9, "reader_process: after deinterlacing: useful_bytes: %d, stripe_fill: %d\n",
7661 	       useful_bytes, stripe_fill);
7662 	}
7663       if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && !s->duplex_rear_valid) {
7664         /* Here we flip the image by writing the lines from the end of the file to the beginning. */
7665 	unsigned int absline = (processed_bytes - stripe_fill) / s->avdimen.hw_bytes_per_line;
7666 	unsigned int abslines = absline + useful_bytes / s->avdimen.hw_bytes_per_line;
7667 	uint8_t* ptr = stripe_data;
7668 	for ( ; absline < abslines; ++absline) {
7669           fseek (rear_fp, ((0 - s->params.lines) - absline - 2) * s->avdimen.hw_bytes_per_line, SEEK_SET);
7670           fwrite (ptr, s->avdimen.hw_bytes_per_line, 1, rear_fp);
7671           useful_bytes -= s->avdimen.hw_bytes_per_line;
7672           stripe_fill -= s->avdimen.hw_bytes_per_line;
7673           ptr += s->avdimen.hw_bytes_per_line;
7674         }
7675 	DBG (9, "reader_process: after page flip: useful_bytes: %d, stripe_fill: %d\n",
7676 	       useful_bytes, stripe_fill);
7677       } else {
7678 
7679       /*
7680        * Perform needed data conversions (packing, ...) and/or copy the
7681        * image data.
7682        */
7683 
7684       if (s->c_mode != AV_TRUECOLOR && s->c_mode != AV_TRUECOLOR16)
7685 	/* simple copy */
7686 	{
7687 	  memcpy (out_data, stripe_data, useful_bytes);
7688 	}
7689       else /* AV_TRUECOLOR* */
7690 	{
7691 	  /* WARNING: DO NOT MODIFY MY (HOPEFULLY WELL) OPTIMIZED
7692 	     ALGORITHMS BELOW, WITHOUT UNDERSTANDING THEM FULLY ! */
7693 	  if (s->avdimen.line_difference > 0) /* color-pack */
7694 	    {
7695 	      /* TODO: add 16bit per sample code? */
7696 	      unsigned int i;
7697 	      int c_offset = s->avdimen.line_difference * s->avdimen.hw_bytes_per_line;
7698 
7699 	      uint8_t* r_ptr = stripe_data;
7700 	      uint8_t* g_ptr = stripe_data + c_offset + 1;
7701 	      uint8_t* b_ptr = stripe_data + 2 * c_offset + 2;
7702 
7703 	      for (i = 0; i < useful_bytes;) {
7704 		out_data [i++] = *r_ptr; r_ptr += 3;
7705 		out_data [i++] = *g_ptr; g_ptr += 3;
7706 		out_data [i++] = *b_ptr; b_ptr += 3;
7707 	      }
7708 	    } /* end color pack */
7709 	  else if (dev->inquiry_needs_line_pack) /* line-pack */
7710 	    {
7711 	      /* TODO: add 16bit per sample code? */
7712 	      int i = 0, l, p;
7713 	      const int lines = useful_bytes / s->avdimen.hw_bytes_per_line;
7714 
7715 	      for (l = 0; l < lines; ++l)
7716 		{
7717 		  uint8_t* r_ptr = stripe_data + (s->avdimen.hw_bytes_per_line * l);
7718 		  uint8_t* g_ptr = r_ptr + s->avdimen.hw_pixels_per_line;
7719 		  uint8_t* b_ptr = g_ptr + s->avdimen.hw_pixels_per_line;
7720 
7721 		  for (p = 0; p < s->avdimen.hw_pixels_per_line; ++p) {
7722 		    out_data [i++] = *(r_ptr++);
7723 		    out_data [i++] = *(g_ptr++);
7724 		    out_data [i++] = *(b_ptr++);
7725 		  }
7726 		}
7727 	    } /* end line pack */
7728 	  else /* else no packing was required -> simple copy */
7729 	    {
7730 	      memcpy (out_data, stripe_data, useful_bytes);
7731 	    }
7732 	} /* end if AV_TRUECOLOR* */
7733 
7734       /* FURTHER POST-PROCESSING ON THE FINAL OUTPUT DATA */
7735 
7736       /* maybe mirroring in ADF mode */
7737       if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_adf_need_mirror)
7738         {
7739 	  if ( (s->c_mode != AV_TRUECOLOR) ||
7740 	       (s->c_mode == AV_TRUECOLOR && dev->inquiry_adf_bgr_order) )
7741 	  {
7742 	    /* Mirroring with bgr -> rgb conversion: Just mirror the
7743 	     * whole line */
7744 
7745 	    int l;
7746 	    int lines = useful_bytes / s->avdimen.hw_bytes_per_line;
7747 
7748 	    for (l = 0; l < lines; ++l)
7749 	      {
7750 		uint8_t* begin_ptr = out_data + (l * s->avdimen.hw_bytes_per_line);
7751 		uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line;
7752 
7753 		while (begin_ptr < end_ptr) {
7754 		  uint8_t tmp;
7755 		  tmp = *begin_ptr;
7756 		  *begin_ptr++ = *end_ptr;
7757 		  *end_ptr-- = tmp;
7758 		}
7759 	      }
7760 	  }
7761 	else /* non trivial mirroring */
7762 	  {
7763 	    /* Non-trivial Mirroring with element swapping */
7764 
7765 	    int l;
7766 	    int lines = useful_bytes / s->avdimen.hw_bytes_per_line;
7767 
7768 	    for (l = 0; l < lines; ++l)
7769 	      {
7770 		uint8_t* begin_ptr = out_data + (l * s->avdimen.hw_bytes_per_line);
7771 		uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line - 3;
7772 
7773 		while (begin_ptr < end_ptr) {
7774 		  uint8_t tmp;
7775 
7776 		  /* R */
7777 		  tmp = *begin_ptr;
7778 		  *begin_ptr++ = *end_ptr;
7779 		  *end_ptr++ = tmp;
7780 
7781 		  /* G */
7782 		  tmp = *begin_ptr;
7783 		  *begin_ptr++ = *end_ptr;
7784 		  *end_ptr++ = tmp;
7785 
7786 		  /* B */
7787 		  tmp = *begin_ptr;
7788 		  *begin_ptr++ = *end_ptr;
7789 		  *end_ptr = tmp;
7790 
7791 		  end_ptr -= 5;
7792 		}
7793 	      }
7794 	  }
7795       } /* end if mirroring needed */
7796 
7797       /* byte swapping and software calibration 16bit mode */
7798       if (s->c_mode == AV_GRAYSCALE12 ||
7799           s->c_mode == AV_GRAYSCALE16 ||
7800           s->c_mode == AV_TRUECOLOR12 ||
7801           s->c_mode == AV_TRUECOLOR16) {
7802 
7803 	int l;
7804 	int lines = useful_bytes / s->avdimen.hw_bytes_per_line;
7805 
7806 	uint8_t* dark_avg_data = s->dark_avg_data;
7807 	uint8_t* white_avg_data = s->white_avg_data;
7808 
7809 	uint8_t* begin_ptr = out_data;
7810 	uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line;
7811 	uint8_t* line_ptr;
7812 
7813         double scale = 1.0;
7814         if (s->c_mode == AV_GRAYSCALE12 || s->c_mode == AV_TRUECOLOR12)
7815           scale = (double) (1<<4);
7816 
7817 	while (begin_ptr < end_ptr) {
7818 	  uint16_t dark_avg = 0;
7819 	  uint16_t white_avg = WHITE_MAP_RANGE;
7820 
7821 	  if (dark_avg_data)
7822 	    dark_avg = get_double_le (dark_avg_data);
7823 	  if (white_avg_data)
7824 	    white_avg = get_double_le (white_avg_data);
7825 
7826 	  line_ptr = begin_ptr;
7827 	  for (l = 0; l < lines; ++ l)
7828 	    {
7829 	      double v = (double) get_double_le (line_ptr) * scale;
7830 	      uint16_t v2;
7831 	      if (0)
7832 		v = (v - dark_avg) * white_avg / WHITE_MAP_RANGE;
7833 
7834 	      v2 = v < 0xFFFF ? v : 0xFFFF;
7835 
7836 	      /* SANE Standard 3.2.1 "... bytes of each sample value are
7837 		 transmitted in the machine's native byte order." */
7838 	      *line_ptr = v2;
7839 
7840 	      line_ptr += s->avdimen.hw_bytes_per_line;
7841 	    }
7842 
7843 	  begin_ptr += 2;
7844 	  if (dark_avg_data)
7845 	    dark_avg_data += 2;
7846 	  if (white_avg_data)
7847 	    white_avg_data += 2;
7848 	}
7849       }
7850 
7851       /* SOFTWARE SCALING WITH INTERPOLATION (IF NECESSARY) */
7852 
7853       if (s->avdimen.hw_xres == s->avdimen.xres &&
7854 	  s->avdimen.hw_yres == s->avdimen.yres) /* No scaling */
7855 	{
7856           fwrite (out_data, useful_bytes, 1, fp);
7857           line += useful_bytes / s->avdimen.hw_bytes_per_line;
7858 	}
7859       else /* Software scaling - watch out - this code bites back! */
7860 	{
7861 	  int x;
7862 	  /* for convenience in the 16bit code path */
7863 	  uint16_t* out_data16 = (uint16_t*) out_data;
7864 
7865 	  const int hw_line_end = hw_line + useful_bytes / s->avdimen.hw_bytes_per_line;
7866 
7867 	  /* on-the-fly bi-linear interpolation */
7868 	  while (1) {
7869 	    double by = (-1.0 + s->avdimen.hw_lines) * line / (s->avdimen.hw_lines * s->avdimen.xres / s->avdimen.hw_xres + s->val[OPT_BACKGROUND].w);
7870 	    int sy = (int)floor(by);
7871 	    int ydist = (int) ((by - sy) * 256);
7872 	    int syy = sy + 1;
7873 
7874 	    const int hwbpl = s->avdimen.hw_bytes_per_line;
7875 
7876 	    uint8_t* dst = ip_data;
7877 	    uint16_t* dst16 = (uint16_t*) ip_data;
7878 	    unsigned int v; /* accumulator */
7879 
7880 	    /* Break out if we do not have the hw source line - yet,
7881 	       or when we are past the end of wanted data */
7882 	    if (deinterlace != NONE && !s->duplex_rear_valid && syy >= s->avdimen.hw_lines) {
7883 	      DBG (7, "reader_process: skip due past intended front page lines: %d\n", sy);
7884 	      break;
7885 	    }
7886 	    if (sy >= hw_line_end || syy >= hw_line_end) {
7887 	      DBG (3, "reader_process: source line %d-%d not yet avail\n",
7888 		   sy, syy);
7889 	      break;
7890 	    }
7891 
7892 	    /* convert to offset in current stripe */
7893 	    sy -= hw_line;
7894 	    syy -= hw_line;
7895 
7896 	    if (sy < -1) {
7897 	      DBG (1, "reader_process: need more history: %d???\n", sy);
7898 	      sy = -1;
7899 	    }
7900 
7901 	    DBG (8, "reader_process: out line: %d <- from: %d-%d\n",
7902 		 line, sy, syy);
7903 
7904 	    for (x = 0; x < s->params.pixels_per_line; ++x) {
7905 	      const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line;
7906 	      const int sx = (int)floor(bx);
7907 	      const int xdist = (int) ((bx - sx) * 256);
7908 	      const int sxx = sx + 1;
7909 
7910 	      if (x == 0 || x == s->params.pixels_per_line - 1)
7911 		 DBG (8, "reader_process: x: %d <- from: %d-%d\n",
7912 		      x, sx, sxx);
7913 
7914 	      switch (s->c_mode) {
7915 	      case AV_THRESHOLDED:
7916 	      case AV_DITHERED:
7917 		{
7918 		  /* Repeating this over and over again is not fast, but
7919 		     as a seldom used code-path we want it readable.
7920 		     x/8 is the byte, and x%8 the bit position. */
7921 		  v =
7922 		    ( ((out_data [sy*hwbpl  + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * (256-ydist) +
7923 		      ((out_data [sy*hwbpl  + sxx/8] >> (7-sxx%8)) & 1) * xdist       * (256-ydist) +
7924 		      ((out_data [syy*hwbpl + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * ydist +
7925 		      ((out_data [syy*hwbpl + sxx/8] >> (7-sxx%8)) & 1) * xdist       * ydist
7926 		      ) / (1 + 1 * 256);
7927 
7928 		  /* Shift and or the result together and eventually
7929 		     jump to the next byte. */
7930 		  *dst = (*dst << 1) | ((v>>7)&1);
7931 		    if (x % 8 == 7)
7932 		     ++dst;
7933 		}
7934 		break;
7935 
7936 	      case AV_GRAYSCALE:
7937 		{
7938 		  v =
7939 		    ( out_data [sy*hwbpl  + sx ] * (256-xdist) * (256-ydist) +
7940 		      out_data [sy*hwbpl  + sxx] * xdist       * (256-ydist) +
7941 		      out_data [syy*hwbpl + sx ] * (256-xdist) * ydist +
7942 		      out_data [syy*hwbpl + sxx] * xdist       * ydist
7943 		      ) / (256 * 256);
7944 		  *dst++ = v;
7945 		}
7946 		break;
7947 
7948 	      case AV_GRAYSCALE12:
7949 	      case AV_GRAYSCALE16:
7950 		{
7951 		  /* TODO: test! */
7952 		  v =
7953 		    ( out_data16 [sy*hwbpl  + sx ] * (256-xdist) * (256-ydist) +
7954 		      out_data16 [sy*hwbpl  + sxx] * xdist       * (256-ydist) +
7955 		      out_data16 [syy*hwbpl + sx ] * (256-xdist) * ydist +
7956 		      out_data16 [syy*hwbpl + sxx] * xdist       * ydist
7957 		      ) / (256 * 256);
7958 		  *dst16++ = v;
7959 		}
7960 		break;
7961 
7962 	      case AV_TRUECOLOR:
7963 		{
7964 		  int c;
7965 		  for (c = 0; c < 3; ++c)
7966 		    {
7967 		      v =
7968 			( out_data [sy*hwbpl  + sx*3  + c] * (256-xdist) * (256-ydist) +
7969 			  out_data [sy*hwbpl  + sxx*3 + c] * xdist       * (256-ydist) +
7970 			  out_data [syy*hwbpl + sx*3  + c] * (256-xdist) * ydist +
7971 			  out_data [syy*hwbpl + sxx*3 + c] * xdist       * ydist
7972 			  ) / (256 * 256);
7973 		      *dst++ = v;
7974 		    }
7975 		}
7976 		break;
7977 
7978 	      case AV_TRUECOLOR12:
7979 	      case AV_TRUECOLOR16:
7980 		{
7981 		  /* TODO: test! */
7982 		  int c;
7983 		  for (c = 0; c < 3; ++c)
7984 		    {
7985 		      v =
7986 			( out_data16 [sy*hwbpl  + sx*3  + c] * (256-xdist) * (256-ydist) +
7987 			  out_data16 [sy*hwbpl  + sxx*3 + c] * xdist       * (256-ydist) +
7988 			  out_data16 [syy*hwbpl + sx*3  + c] * (256-xdist) * ydist +
7989 			  out_data16 [syy*hwbpl + sxx*3 + c] * xdist       * ydist
7990 			  ) / (256 * 256);
7991 		      *dst16++ = v;
7992 		    }
7993 		}
7994 		break;
7995 
7996 	      case AV_COLOR_MODE_LAST:
7997 		; /* silence compiler warning */
7998 	      }
7999 	    }
8000 	    fwrite (ip_data, s->params.bytes_per_line, 1, fp);
8001 	    ++line;
8002 	  }
8003 	  /* copy one line of history for the next pass */
8004 	  memcpy (ip_history,
8005 	          out_data + useful_bytes - s->avdimen.hw_bytes_per_line,
8006 		  s->avdimen.hw_bytes_per_line);
8007 	}
8008       }
8009 
8010       /* save image date in stripe buffer for next next stripe */
8011       stripe_fill -= useful_bytes;
8012       if (stripe_fill > 0)
8013 	memcpy (stripe_data, stripe_data + useful_bytes, stripe_fill);
8014 
8015       hw_line += useful_bytes / s->avdimen.hw_bytes_per_line;
8016 
8017       DBG (3, "reader_process: end of iteration\n");
8018     } /* end while not all lines or inf. mode */
8019 
8020   DBG (3, "reader_process: i/o loop finished\n");
8021   if (exit_status == SANE_STATUS_GOOD)
8022     exit_status = SANE_STATUS_EOF;
8023 
8024   if (raw_fp)
8025     fclose (raw_fp);
8026 
8027   /* maybe we need to fill in some white data */
8028   if (exit_status == SANE_STATUS_EOF && line < s->params.lines) {
8029     DBG (3, "reader_process: padding with white data\n");
8030     memset (out_data, gray_mode ? 0xff : 0x00, s->params.bytes_per_line);
8031 
8032     DBG (6, "reader_process: padding line %d - %d\n",
8033 	 line, s->params.lines);
8034     while (line < s->params.lines) {
8035       fwrite (out_data, s->params.bytes_per_line, 1, fp);
8036       ++line;
8037     }
8038   }
8039 
8040   /* ADF offset compensation */
8041   if (dev->adf_offset_compensation) {
8042 
8043     long lines;
8044     uint8_t* buffer;
8045 
8046     buffer = malloc (s->params.bytes_per_line);
8047     lines = ftell(fp) / s->params.bytes_per_line;
8048     rewind(fp);
8049 
8050     for (long line = 0; line < lines; line++) {
8051       fread(buffer, s->params.bytes_per_line, 1, fp);
8052 
8053       if ( (!s->duplex_rear_valid && (line < s->avdimen.offset.front.top)) ||
8054            (s->duplex_rear_valid && (line < s->avdimen.offset.rear.top)) ) {
8055         DBG (7, "reader_process: skip due read offset line: %ld\n", line);
8056         continue;
8057       }
8058 
8059       if ( (!s->duplex_rear_valid && (line > (lines - s->avdimen.offset.front.bottom))) ||
8060            (s->duplex_rear_valid && (line > (lines - s->avdimen.offset.rear.bottom))) ) {
8061         DBG (7, "reader_process: skip due read offset line: %ld to %ld\n", line, lines);
8062         break; /* nothing more to write, so break out here */
8063       }
8064 
8065       fwrite(buffer, s->params.bytes_per_line, 1, fp_fd);
8066     }
8067   }
8068 
8069   /* Eject film holder and/or release_unit - but only for
8070      non-duplex-rear / non-virtual scans. */
8071   if ((deinterlace != NONE && s->duplex_rear_valid) ||
8072      ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && s->duplex_rear_valid))
8073     {
8074       DBG (1, "reader_process: virtual duplex scan - no device cleanup!\n");
8075     }
8076   else
8077     {
8078       /* poll the cancel button if the scanner is marked as having one */
8079       if (dev->hw->feature_type & AV_CANCEL_BUTTON) {
8080 	if (get_button_status (s) == SANE_STATUS_CANCELLED)
8081 	  exit_status =  SANE_STATUS_CANCELLED;
8082       }
8083 
8084       status = release_unit (s, 0);
8085       if (status != SANE_STATUS_GOOD)
8086 	DBG (1, "reader_process: release_unit failed\n");
8087 
8088       if (dev->inquiry_new_protocol && dev->scanner_type == AV_FILM) {
8089 	status = object_position (s, AVISION_SCSI_OP_GO_HOME);
8090 	if (status != SANE_STATUS_GOOD)
8091 	  DBG (1, "reader_process: object position go-home failed!\n");
8092       }
8093     }
8094 
8095   if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->page % 2) {
8096     /* front page of flipping duplex */
8097     if (exit_status == SANE_STATUS_EOF) {
8098       if (s->val[OPT_ADF_FLIP].w) {
8099         /* The page flip bit must be reset after every scan, but if the
8100          * user doesn't care, there's no reason to reset.
8101          */
8102         status = set_window (s);
8103         if (status != SANE_STATUS_GOOD) {
8104           DBG (1, "reader_process: set scan window command failed: %s\n",
8105           sane_strstatus (status));
8106           return status;
8107         }
8108       }
8109       /* We run in a separate process or thread.  In the latter case,
8110          any change we make to s before the reader_process invocation
8111          needs to be reverted. */
8112       SANE_Int lines = s->params.lines;
8113       s->page += 1;
8114       s->params.lines = -line;
8115       exit_status = reader_process (s);
8116       s->params.lines = lines;
8117       s->page -= 1;
8118     }
8119     /* TODO:
8120     * else {
8121     *   spit out the page if an error was encountered...
8122     *   assuming the error won't prevent it.
8123     * } */
8124   } else {
8125     fclose (fp);
8126   }
8127   if (rear_fp)
8128     fclose (rear_fp);
8129 
8130   if (fp_fd)
8131     fclose(fp_fd);
8132 
8133   if (ip_data) free (ip_data);
8134   if (ip_history)
8135     free (ip_history);
8136   else
8137     free (out_data); /* if we have ip_history out_data is included there */
8138 
8139   free (stripe_data);
8140 
8141   DBG (3, "reader_process: returning success\n");
8142   return exit_status;
8143 }
8144 
8145 /* SANE callback to attach a SCSI device */
8146 static SANE_Status
attach_one_scsi(const char * dev)8147 attach_one_scsi (const char* dev)
8148 {
8149   attach (dev, AV_SCSI, 0);
8150   return SANE_STATUS_GOOD;
8151 }
8152 
8153 /* SANE callback to attach a USB device */
8154 static SANE_Status
attach_one_usb(const char * dev)8155 attach_one_usb (const char* dev)
8156 {
8157   attach (dev, AV_USB, 0);
8158   return SANE_STATUS_GOOD;
8159 }
8160 
8161 static SANE_Status
sane_reload_devices(void)8162 sane_reload_devices (void)
8163 {
8164   FILE* fp;
8165 
8166   char line[PATH_MAX];
8167   const char* cp = 0;
8168   char* word;
8169   int linenumber = 0;
8170   int model_num = 0;
8171 
8172   sanei_usb_init ();
8173   fp = sanei_config_open (AVISION_CONFIG_FILE);
8174   if (fp <= (FILE*)0)
8175     {
8176       DBG (1, "sane_reload_devices: No config file present!\n");
8177     }
8178   else
8179     {
8180       /* first parse the config file */
8181       while (sanei_config_read  (line, sizeof (line), fp))
8182 	{
8183 	  attaching_hw = 0;
8184 
8185 	  word = NULL;
8186 	  ++ linenumber;
8187 
8188 	  DBG (5, "sane_reload_devices: parsing config line \"%s\"\n",
8189 	       line);
8190 
8191 	  cp = sanei_config_get_string (line, &word);
8192 
8193 	  if (!word || cp == line) {
8194 	    DBG (5, "sane_reload_devices: config file line %d: ignoring empty line\n",
8195 		 linenumber);
8196 	    if (word) {
8197 	      free (word);
8198 	      word = NULL;
8199 	    }
8200 	    continue;
8201 	  }
8202 
8203 	  if (!word) {
8204 	    DBG (1, "sane_reload_devices: config file line %d: could not be parsed\n",
8205 		 linenumber);
8206 	    continue;
8207 	  }
8208 
8209 	  if (word[0] == '#') {
8210 	    DBG (5, "sane_reload_devices: config file line %d: ignoring comment line\n",
8211 		 linenumber);
8212 	    free (word);
8213 	    word = NULL;
8214 	    continue;
8215 	  }
8216 
8217 	  if (strcmp (word, "option") == 0)
8218 	    {
8219 	      free (word);
8220 	      word = NULL;
8221 	      cp = sanei_config_get_string (cp, &word);
8222 
8223 	      if (strcmp (word, "disable-gamma-table") == 0) {
8224 		DBG (3, "sane_reload_devices: config file line %d: disable-gamma-table\n",
8225 		     linenumber);
8226 		disable_gamma_table = SANE_TRUE;
8227 	      }
8228 	      else if (strcmp (word, "disable-calibration") == 0) {
8229 		DBG (3, "sane_reload_devices: config file line %d: disable-calibration\n",
8230 		     linenumber);
8231 		disable_calibration = SANE_TRUE;
8232 	      }
8233 	      else if (strcmp (word, "force-calibration") == 0) {
8234 		DBG (3, "sane_reload_devices: config file line %d: force-calibration\n",
8235 		     linenumber);
8236 		force_calibration = SANE_TRUE;
8237 	      }
8238 	      else if (strcmp (word, "force-a4") == 0) {
8239 		DBG (3, "sane_reload_devices: config file line %d: enabling force-a4\n",
8240 		     linenumber);
8241 		force_a4 = SANE_TRUE;
8242 	      }
8243 	      else if (strcmp (word, "force-a3") == 0) {
8244 		DBG (3, "sane_reload_devices: config file line %d: enabling force-a3\n",
8245 		     linenumber);
8246 		force_a3 = SANE_TRUE;
8247 	      }
8248 	      else if (strcmp (word, "skip-adf") == 0) {
8249 		DBG (3, "sane_reload_devices: config file line %d: enabling skip-adf\n",
8250 		     linenumber);
8251 		skip_adf = SANE_TRUE;
8252 	      }
8253 	      else if (strcmp (word, "static-red-calib") == 0) {
8254 		DBG (3, "sane_reload_devices: config file line %d: static red calibration\n",
8255 		     linenumber);
8256 		static_calib_list [0] = SANE_TRUE;
8257 	      }
8258 	      else if (strcmp (word, "static-green-calib") == 0) {
8259 		DBG (3, "sane_reload_devices: config file line %d: static green calibration\n",
8260 		    linenumber);
8261 		static_calib_list [1] = SANE_TRUE;
8262 	      }
8263 	      else if (strcmp (word, "static-blue-calib") == 0) {
8264 		DBG (3, "sane_reload_devices: config file line %d: static blue calibration\n",
8265 		    linenumber);
8266 		static_calib_list [2] = SANE_TRUE;
8267 	      }
8268 	      else
8269 		DBG (1, "sane_reload_devices: config file line %d: options unknown!\n",
8270 		    linenumber);
8271 	    }
8272 	  else if (strcmp (word, "usb") == 0) {
8273 	    DBG (2, "sane_reload_devices: config file line %d: trying to attach USB:`%s'\n",
8274 		 linenumber, line);
8275 	    /* try to attach USB device */
8276 	    sanei_usb_attach_matching_devices (line, attach_one_usb);
8277 	  }
8278 	  else if (strcmp (word, "scsi") == 0) {
8279 	    DBG (2, "sane_reload_devices: config file line %d: trying to attach SCSI: %s'\n",
8280 		 linenumber, line);
8281 
8282 	    /* the last time I verified (2003-03-18) this function
8283 	       only matches SCSI devices ... */
8284 	    sanei_config_attach_matching_devices (line, attach_one_scsi);
8285 	  }
8286 	  else {
8287 	    DBG (1, "sane_reload_devices: config file line %d: OBSOLETE !! use the scsi keyword!\n",
8288 		linenumber);
8289 	    DBG (1, "sane_reload_devices:   (see man sane-avision for details): trying to attach SCSI: %s'\n",
8290 		line);
8291 
8292 	    /* the last time I verified (2003-03-18) this function
8293 	       only matched SCSI devices ... */
8294 	    sanei_config_attach_matching_devices (line, attach_one_scsi);
8295 	  }
8296 	  free (word);
8297 	  word = NULL;
8298 	} /* end while read */
8299 
8300       fclose (fp);
8301 
8302       if (word)
8303 	free (word);
8304     } /* end if fp */
8305 
8306   /* search for all supported SCSI/USB devices */
8307   while (Avision_Device_List [model_num].scsi_mfg != NULL ||
8308          Avision_Device_List [model_num].real_mfg != NULL)
8309     {
8310       /* also potentially accessed from the attach_* callbacks */
8311       attaching_hw = &(Avision_Device_List [model_num]);
8312 	if (attaching_hw->scsi_mfg != NULL)
8313 	  sanei_scsi_find_devices (attaching_hw->scsi_mfg,
8314 				               attaching_hw->scsi_model, NULL,
8315 				               -1, -1, -1, -1,
8316 				               attach_one_scsi);
8317 
8318 	if (attaching_hw->usb_vendor != 0 && attaching_hw->usb_product != 0 )
8319 	{
8320 	  DBG (1, "sane_reload_devices: Trying to find USB device %.4x %.4x ...\n",
8321 	       attaching_hw->usb_vendor,
8322 	       attaching_hw->usb_product);
8323 
8324 	  /* TODO: check return value */
8325 	  if (sanei_usb_find_devices (attaching_hw->usb_vendor,
8326 				      attaching_hw->usb_product,
8327 				      attach_one_usb) != SANE_STATUS_GOOD) {
8328 	    DBG (1, "sane_reload_devices: error during USB device detection!\n");
8329 	  }
8330 	}
8331       ++ model_num;
8332     } /* end for all devices in supported list */
8333 
8334   attaching_hw = 0;
8335   return SANE_STATUS_GOOD;
8336 }
8337 
8338 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)8339 sane_init (SANE_Int* version_code, SANE_Auth_Callback authorize)
8340 {
8341   authorize = authorize; /* silence gcc */
8342 
8343   DBG_INIT();
8344 
8345 #ifdef AVISION_STATIC_DEBUG_LEVEL
8346   DBG_LEVEL = AVISION_STATIC_DEBUG_LEVEL;
8347 #endif
8348 
8349   DBG (3, "sane_init:(Version: %i.%i Build: %i)\n",
8350        SANE_CURRENT_MAJOR, V_MINOR, BACKEND_BUILD);
8351 
8352   /* must come first */
8353   sanei_thread_init ();
8354 
8355   if (version_code)
8356     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BACKEND_BUILD);
8357 
8358   sane_reload_devices ();
8359 
8360   return SANE_STATUS_GOOD;
8361 }
8362 
8363 void
sane_exit(void)8364 sane_exit (void)
8365 {
8366   Avision_Device* dev;
8367   Avision_Device* next;
8368 
8369   DBG (3, "sane_exit:\n");
8370 
8371   for (dev = first_dev; dev; dev = next) {
8372     next = dev->next;
8373     /* no warning for stripping const - C lacks a const_cast<> */
8374     free ((void*)(size_t) dev->sane.name);
8375 
8376     free (dev);
8377   }
8378   first_dev = NULL;
8379 
8380   free(devlist);
8381   devlist = NULL;
8382 }
8383 
8384 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)8385 sane_get_devices (const SANE_Device*** device_list, SANE_Bool local_only)
8386 {
8387   Avision_Device* dev;
8388   int i;
8389 
8390   local_only = local_only; /* silence gcc */
8391 
8392   DBG (3, "sane_get_devices:\n");
8393 
8394   sane_reload_devices ();
8395 
8396   if (devlist)
8397     free (devlist);
8398 
8399   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
8400   if (!devlist)
8401     return SANE_STATUS_NO_MEM;
8402 
8403   i = 0;
8404   for (dev = first_dev; i < num_devices; dev = dev->next)
8405     devlist[i++] = &dev->sane;
8406   devlist[i++] = 0;
8407 
8408   *device_list = devlist;
8409   return SANE_STATUS_GOOD;
8410 }
8411 
8412 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)8413 sane_open (SANE_String_Const devicename, SANE_Handle *handle)
8414 {
8415   Avision_Device* dev;
8416   SANE_Status status;
8417   Avision_Scanner* s;
8418   int i, j;
8419   uint8_t inquiry_result[AVISION_INQUIRY_SIZE_V1];
8420 
8421   DBG (3, "sane_open:\n");
8422 
8423   if (devicename[0]) {
8424     for (dev = first_dev; dev; dev = dev->next)
8425       if (strcmp (dev->sane.name, devicename) == 0)
8426 	break;
8427 
8428     if (dev) {
8429       status = attach (devicename, dev->connection.connection_type, &dev);
8430       if (status != SANE_STATUS_GOOD)
8431 	return status;
8432     }
8433   } else {
8434     /* empty devicename -> use first device */
8435     dev = first_dev;
8436   }
8437 
8438   if (!dev)
8439     return SANE_STATUS_INVAL;
8440 
8441   s = malloc (sizeof (*s));
8442   if (!s)
8443     return SANE_STATUS_NO_MEM;
8444 
8445   /* initialize ... */
8446   /* the other states (scanning, ...) rely on this memset (0) */
8447   memset (s, 0, sizeof (*s));
8448 
8449   /* initialize connection state */
8450   s->av_con.connection_type = dev->connection.connection_type;
8451   s->av_con.usb_status = dev->connection.usb_status;
8452   s->av_con.scsi_fd = -1;
8453   s->av_con.usb_dn = -1;
8454 
8455   sanei_thread_initialize (s->reader_pid);
8456   s->read_fds = -1;
8457 
8458   s->hw = dev;
8459 
8460   /* We initialize the table to a gamma value of 2.22, since this is what
8461      papers about Colorimetry suggest.
8462 
8463 	http://www.poynton.com/GammaFAQ.html
8464 
8465      Avision's driver defaults to 2.2 though.
8466 
8467      MN: This is not true for at least Kodak i1120's windows driver.
8468          Some real-world testing showed that a gamma of 1.0 is needed
8469          for this scanner to give decent scan results. Add an option for this...
8470   */
8471 
8472   {
8473     double gamma = 2.22;
8474     if (s->hw->hw->feature_type & AV_GAMMA_10)
8475       gamma = 1.0;
8476     const double one_over_gamma = 1. / gamma;
8477 
8478     for (i = 0; i < 4; ++ i)
8479       for (j = 0; j < 256; ++ j)
8480 	s->gamma_table[i][j] = pow( (double) j / 255, one_over_gamma) * 255;
8481   }
8482 
8483   /* insert newly opened handle into list of open handles: */
8484   s->next = first_handle;
8485   first_handle = s;
8486   *handle = s;
8487 
8488   /* open the device */
8489   if (! avision_is_open (&s->av_con) ) {
8490 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
8491     DBG (1, "sane_open: using open_extended\n");
8492     status = avision_open_extended (s->hw->sane.name, &s->av_con, sense_handler, 0,
8493 				    &(dev->scsi_buffer_size));
8494 #else
8495     status = avision_open (s->hw->sane.name, &s->av_con, sense_handler, 0);
8496 #endif
8497     if (status != SANE_STATUS_GOOD) {
8498       DBG (1, "sane_open: open of %s failed: %s\n",
8499 	   s->hw->sane.name, sane_strstatus (status));
8500       return status;
8501     }
8502     DBG (1, "sane_open: got %d scsi_max_request_size\n", dev->scsi_buffer_size);
8503   }
8504 
8505   /* first: re-awake the device with an inquiry, some devices are flunk while initializing
8506      the usb connection and like a inquiry to come first ... (AV610 et.al.) */
8507   status = inquiry (s->av_con, inquiry_result, sizeof(inquiry_result));
8508   if (status != SANE_STATUS_GOOD) {
8509 	DBG (1, "sane_open: awakening inquiry failed: %s\n", sane_strstatus (status));
8510 	return status;
8511   }
8512 
8513   status = wait_ready (&s->av_con, 1);
8514   if (status != SANE_STATUS_GOOD) {
8515     DBG (1, "sane_open: wait_ready() failed: %s\n", sane_strstatus (status));
8516     return status;
8517   }
8518 
8519   /* update settings based on additional accessory information */
8520   status = additional_probe (s);
8521   if (status != SANE_STATUS_GOOD) {
8522     DBG (1, "sane_open: additional probe failed: %s\n", sane_strstatus (status));
8523     return status;
8524   }
8525 
8526   /* initialize the options */
8527   init_options (s);
8528 
8529   if (dev->inquiry_duplex_interlaced &&
8530       (dev->hw->offset.first != 0 ||
8531        dev->hw->offset.front.top != 0 ||
8532        dev->hw->offset.front.bottom != 0 ||
8533        dev->hw->offset.duplex.front.top != 0 ||
8534        dev->hw->offset.duplex.front.bottom != 0 ||
8535        dev->hw->offset.duplex.rear.top != 0 ||
8536        dev->hw->offset.duplex.rear.bottom != 0) )
8537     dev->adf_offset_compensation = SANE_TRUE;
8538 
8539   if (dev->adf_offset_compensation) {
8540     strncpy(s->duplex_offtmp_fname, "/tmp/avision-offtmp-XXXXXX", PATH_MAX);
8541 
8542     if (! mktemp(s->duplex_offtmp_fname) ) {
8543       DBG (1, "sane_open: failed to generate temporary fname for ADF offset compensation temp file\n");
8544       return SANE_STATUS_NO_MEM;
8545     }
8546     else {
8547       DBG (1, "sane_open: temporary fname for ADF offset compensation temp file: %s\n",
8548 	   s->duplex_offtmp_fname);
8549     }
8550   }
8551 
8552   if (dev->inquiry_duplex_interlaced || dev->scanner_type == AV_FILM ||
8553       dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) {
8554     /* Might need at least *DOS (Windows flavour and OS/2) portability fix
8555        However, I was told Cygwin (et al.) takes care of it. */
8556     strncpy(s->duplex_rear_fname, "/tmp/avision-rear-XXXXXX", PATH_MAX);
8557 
8558     if (! mkstemp(s->duplex_rear_fname) ) {
8559       DBG (1, "sane_open: failed to generate temporary fname for duplex scans\n");
8560       return SANE_STATUS_NO_MEM;
8561     }
8562     else {
8563       DBG (1, "sane_open: temporary fname for duplex scans: %s\n",
8564 	   s->duplex_rear_fname);
8565     }
8566   }
8567 
8568   /* calibrate film scanners, as this must be done without the
8569      film holder and at the full resolution */
8570   if (dev->scanner_type == AV_FILM)
8571     {
8572       int default_res = s->val[OPT_RESOLUTION].w;
8573       s->val[OPT_RESOLUTION].w = dev->inquiry_optical_res;
8574 
8575       DBG (1, "sane_open: early calibration for film scanner.\n");
8576 
8577       compute_parameters (s);
8578 
8579       status = set_window (s);
8580       if (status != SANE_STATUS_GOOD) {
8581 	DBG (1, "sane_open: set scan window command failed: %s\n",
8582 	     sane_strstatus (status));
8583 	return status;
8584       }
8585 
8586       if (!(dev->hw->feature_type & AV_NO_CALIB))
8587 	{
8588 	  status = normal_calibration (s);
8589 	  if (status != SANE_STATUS_GOOD) {
8590 	    DBG (1, "sane_open: perform calibration failed: %s\n",
8591 		 sane_strstatus (status));
8592 	    return status;
8593 	  }
8594 	}
8595 
8596       if (dev->scanner_type == AV_FILM) {
8597 	status = object_position (s, AVISION_SCSI_OP_GO_HOME);
8598 	if (status != SANE_STATUS_GOOD)
8599 	  DBG (1, "reader_open: object position go-home failed!\n");
8600       }
8601 
8602       s->val[OPT_RESOLUTION].w = default_res;
8603     }
8604 
8605   return SANE_STATUS_GOOD;
8606 }
8607 
8608 void
sane_close(SANE_Handle handle)8609 sane_close (SANE_Handle handle)
8610 {
8611   Avision_Scanner* prev;
8612   Avision_Scanner* s = handle;
8613   int i;
8614 
8615   DBG (3, "sane_close:\n");
8616 
8617   /* close the device */
8618   if (avision_is_open (&s->av_con) ) {
8619     avision_close (&s->av_con);
8620   }
8621 
8622   /* remove handle from list of open handles: */
8623   prev = 0;
8624   for (s = first_handle; s; s = s->next) {
8625     if (s == handle)
8626       break;
8627     prev = s;
8628   }
8629 
8630   /* a handle we know about ? */
8631   if (!s) {
8632     DBG (1, "sane_close: invalid handle %p\n", handle);
8633     return;
8634   }
8635 
8636   if (s->scanning)
8637     do_cancel (handle);
8638 
8639   if (prev)
8640     prev->next = s->next;
8641   else
8642     first_handle = s->next;
8643 
8644   for (i = 1; i < NUM_OPTIONS; ++ i) {
8645     if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) {
8646       free (s->val[i].s);
8647     }
8648   }
8649 
8650   if (s->white_avg_data)
8651     free (s->white_avg_data);
8652   if (s->dark_avg_data)
8653     free (s->dark_avg_data);
8654 
8655   if (s->background_raster)
8656     free (s->background_raster);
8657 
8658   if (*(s->duplex_rear_fname)) {
8659     unlink (s->duplex_rear_fname);
8660     *(s->duplex_rear_fname) = 0;
8661   }
8662 
8663   if (*(s->duplex_offtmp_fname)) {
8664     unlink (s->duplex_offtmp_fname);
8665     *(s->duplex_offtmp_fname) = 0;
8666   }
8667 
8668   free (handle);
8669 }
8670 
8671 const SANE_Option_Descriptor*
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)8672 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
8673 {
8674   Avision_Scanner* s = handle;
8675 
8676   DBG (3, "sane_get_option_descriptor: %d\n", option);
8677 
8678   if ((unsigned) option >= NUM_OPTIONS)
8679     return 0;
8680   return s->opt + option;
8681 }
8682 
8683 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)8684 sane_control_option (SANE_Handle handle, SANE_Int option,
8685 		     SANE_Action action, void* val, SANE_Int* info)
8686 {
8687   Avision_Scanner* s = handle;
8688   Avision_Device* dev = s->hw;
8689   SANE_Status status;
8690   SANE_Word cap;
8691 
8692   DBG (3, "sane_control_option: option=%d, action=%d\n",
8693        (int)option, (int)action);
8694 
8695   DBG (5, "sane_control_option: option=%s, action=%s\n",
8696        s->opt[option].name,
8697        action == SANE_ACTION_GET_VALUE ? "GET" :
8698        (action == SANE_ACTION_SET_VALUE ? "SET" :
8699 	(action == SANE_ACTION_SET_AUTO ? "AUTO" : "UNKNOWN") ) );
8700 
8701   if (info)
8702     *info = 0;
8703 
8704   if (s->scanning)
8705     return SANE_STATUS_DEVICE_BUSY;
8706 
8707   if (option >= NUM_OPTIONS)
8708     return SANE_STATUS_INVAL;
8709 
8710   cap = s->opt[option].cap;
8711 
8712   if (!SANE_OPTION_IS_ACTIVE (cap))
8713     return SANE_STATUS_INVAL;
8714 
8715   if (action == SANE_ACTION_GET_VALUE)
8716     {
8717       switch (option)
8718 	{
8719 	  /* word options: */
8720 	case OPT_PREVIEW:
8721 
8722 	case OPT_RESOLUTION:
8723 	case OPT_SPEED:
8724 	case OPT_TL_X:
8725 	case OPT_TL_Y:
8726 	case OPT_BR_X:
8727 	case OPT_BR_Y:
8728 	case OPT_OVERSCAN_TOP:
8729 	case OPT_OVERSCAN_BOTTOM:
8730 	case OPT_BACKGROUND:
8731 	case OPT_NUM_OPTS:
8732 
8733 	case OPT_BRIGHTNESS:
8734 	case OPT_CONTRAST:
8735 	case OPT_EXPOSURE:
8736 	case OPT_IR:
8737 	case OPT_MULTISAMPLE:
8738 	case OPT_QSCAN:
8739 	case OPT_QCALIB:
8740 	case OPT_PAPERLEN:
8741 	case OPT_ADF_FLIP:
8742 	  *(SANE_Word*) val = s->val[option].w;
8743 	  return SANE_STATUS_GOOD;
8744 
8745 	  /* specially treated word options */
8746 
8747 	case OPT_FRAME:
8748 	  status = get_frame_info (s);
8749 	  *(SANE_Word*) val = s->val[option].w;
8750 	  return status;
8751 
8752 	case OPT_POWER_SAVE_TIME:
8753 	  get_power_save_time (s, &(s->val[option].w));
8754 	  *(SANE_Word*) val = s->val[option].w;
8755 	  return SANE_STATUS_GOOD;
8756 
8757 	  /* word-array options: */
8758 	case OPT_GAMMA_VECTOR:
8759 	case OPT_GAMMA_VECTOR_R:
8760 	case OPT_GAMMA_VECTOR_G:
8761 	case OPT_GAMMA_VECTOR_B:
8762 	  memcpy (val, s->val[option].wa, s->opt[option].size);
8763 	  return SANE_STATUS_GOOD;
8764 
8765 	  /* string options: */
8766 	case OPT_MODE:
8767 	case OPT_SOURCE:
8768 	  strcpy (val, s->val[option].s);
8769 	  return SANE_STATUS_GOOD;
8770 
8771 	  /* specially treated string options */
8772 	case OPT_MESSAGE:
8773 	  if (dev->inquiry_button_control || dev->inquiry_buttons)
8774 	    status = get_button_status (s);
8775 
8776 	  strcpy (val, s->val[option].s);
8777 	  s->val[option].s[0] = 0;
8778 	  return SANE_STATUS_GOOD;
8779 
8780 	case OPT_NVRAM:
8781 	  get_and_parse_nvram (s, s->val[option].s, 1024);
8782 
8783 	  strcpy (val, s->val[option].s);
8784 	  return SANE_STATUS_GOOD;
8785 
8786 	} /* end switch option */
8787     } /* end if GET_ACTION_GET_VALUE */
8788   else if (action == SANE_ACTION_SET_VALUE)
8789     {
8790       if (!SANE_OPTION_IS_SETTABLE (cap))
8791 	return SANE_STATUS_INVAL;
8792 
8793       status = constrain_value (s, option, val, info);
8794       if (status != SANE_STATUS_GOOD)
8795 	return status;
8796 
8797       switch (option)
8798 	{
8799 	  /* side-effect-free word options: */
8800 	case OPT_SPEED:
8801 	case OPT_PREVIEW:
8802 	case OPT_BRIGHTNESS:
8803 	case OPT_CONTRAST:
8804 	case OPT_EXPOSURE:
8805 	case OPT_IR:
8806 	case OPT_MULTISAMPLE:
8807 	case OPT_QSCAN:
8808 	case OPT_QCALIB:
8809 	case OPT_OVERSCAN_TOP:
8810 	case OPT_OVERSCAN_BOTTOM:
8811 	case OPT_BACKGROUND:
8812 	case OPT_PAPERLEN:
8813 	case OPT_ADF_FLIP:
8814 	  s->val[option].w = *(SANE_Word*) val;
8815 	  return SANE_STATUS_GOOD;
8816 
8817 	  /* side-effect-free word-array options: */
8818 	case OPT_GAMMA_VECTOR:
8819 	case OPT_GAMMA_VECTOR_R:
8820 	case OPT_GAMMA_VECTOR_G:
8821 	case OPT_GAMMA_VECTOR_B:
8822 	  memcpy (s->val[option].wa, val, s->opt[option].size);
8823 	  return SANE_STATUS_GOOD;
8824 
8825 	  /* options with side-effects: */
8826 	case OPT_RESOLUTION:
8827 	case OPT_TL_X:
8828 	case OPT_TL_Y:
8829 	case OPT_BR_X:
8830 	case OPT_BR_Y:
8831 
8832 	  s->val[option].w = *(SANE_Word*) val;
8833 
8834 	  if (info)
8835 	    *info |= SANE_INFO_RELOAD_PARAMS;
8836 
8837 	  return SANE_STATUS_GOOD;
8838 
8839 	  /* string options with side-effects: */
8840 	case OPT_SOURCE:
8841 
8842 	  if (s->val[option].s) {
8843 	    free(s->val[option].s);
8844 	  }
8845 	  s->val[option].s = strdup(val);
8846 	  s->source_mode = match_source_mode (dev, s->val[option].s);
8847 	  s->source_mode_dim = match_source_mode_dim (s->source_mode);
8848 
8849 	  /* set side-effects */
8850 	  dev->x_range.max =
8851 	    SANE_FIX ( dev->inquiry_x_ranges[s->source_mode_dim]);
8852 	  dev->y_range.max =
8853 	    SANE_FIX ( dev->inquiry_y_ranges[s->source_mode_dim]);
8854 
8855           if (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX) {
8856             s->opt[OPT_ADF_FLIP].cap &= ~SANE_CAP_INACTIVE;
8857           } else {
8858             s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
8859           }
8860 
8861 	  if (info)
8862 	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
8863 
8864 	  return SANE_STATUS_GOOD;
8865 
8866 	case OPT_MODE:
8867 	  {
8868 	    if (s->val[option].s)
8869 	      free (s->val[option].s);
8870 
8871 	    s->val[option].s = strdup (val);
8872 	    s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s);
8873 
8874 	    /* set to mode specific values */
8875 
8876 	    /* the gamma table related */
8877 	    if (!disable_gamma_table)
8878 	      {
8879 		if (color_mode_is_color (s->c_mode) ) {
8880 		  s->opt[OPT_GAMMA_VECTOR].cap   |= SANE_CAP_INACTIVE;
8881 		  s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
8882 		  s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
8883 		  s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
8884 		}
8885 		else /* gray or mono */
8886 		  {
8887 		    s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
8888 		    s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
8889 		    s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
8890 		    s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
8891 		  }
8892 	      }
8893 	    if (info)
8894 	      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
8895 	    return SANE_STATUS_GOOD;
8896 	  }
8897 	case OPT_FRAME:
8898 	  {
8899 	    SANE_Word frame = *((SANE_Word  *) val);
8900 
8901 	    status = set_frame (s, frame);
8902 	    if (status == SANE_STATUS_GOOD) {
8903 	      s->val[OPT_FRAME].w = frame;
8904 	      dev->current_frame = frame;
8905 	    }
8906 	    return status;
8907 	  }
8908 	case OPT_POWER_SAVE_TIME:
8909 	  {
8910 	    SANE_Word time = *((SANE_Word  *) val);
8911 
8912 	    status = set_power_save_time (s, time);
8913 	    if (status == SANE_STATUS_GOOD)
8914 	      s->val[OPT_POWER_SAVE_TIME].w = time;
8915 	    return status;
8916 	  }
8917 	} /* end switch option */
8918     }
8919   else if (action == SANE_ACTION_SET_AUTO)
8920     {
8921       if (!SANE_OPTION_IS_SETTABLE (cap))
8922 	return SANE_STATUS_INVAL;
8923 
8924       switch (option)
8925 	{
8926 	case OPT_ADF_FLIP:
8927 	  s->val[option].w = SANE_TRUE;
8928 	  return SANE_STATUS_GOOD;
8929 	} /* end switch option */
8930     } /* end else SET_VALUE */
8931   return SANE_STATUS_INVAL;
8932 }
8933 
8934 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)8935 sane_get_parameters (SANE_Handle handle, SANE_Parameters* params)
8936 {
8937   Avision_Scanner* s = handle;
8938 
8939   DBG (3, "sane_get_parameters:\n");
8940 
8941   /* During an actual scan these parameters will have been computed in
8942      sane_start().  Otherwise, the values must be computed on demand.  The
8943      values cannot be changed during a scan to avoid inconsistency. */
8944   if (!s->scanning)
8945     {
8946       DBG (3, "sane_get_parameters: computing parameters\n");
8947       compute_parameters (s);
8948     }
8949 
8950   if (params) {
8951     *params = s->params;
8952     /* add background raster lines */
8953     params->lines += s->val[OPT_BACKGROUND].w;
8954   }
8955 
8956   return SANE_STATUS_GOOD;
8957 }
8958 
8959 SANE_Status
sane_start(SANE_Handle handle)8960 sane_start (SANE_Handle handle)
8961 {
8962   Avision_Scanner* s = handle;
8963   Avision_Device* dev = s->hw;
8964 
8965   SANE_Status status;
8966   int fds [2];
8967   DBG (1, "sane_start:\n");
8968 
8969   /* Make sure there is no scan running!!! */
8970   if (s->scanning)
8971     return SANE_STATUS_DEVICE_BUSY;
8972 
8973   /* Clear cancellation status */
8974   s->cancelled = SANE_FALSE;
8975 
8976   /* Make sure we have a current parameter set. Some of the
8977      parameters will be overwritten below, but that's OK. */
8978   status = sane_get_parameters (s, &s->params);
8979   if (status != SANE_STATUS_GOOD) {
8980     return status;
8981   }
8982 
8983   /* for non ADF scans (e.g. scanimage --batch-prompt on a Flatbed
8984      scanner) make sure we do not assume it's an ADF scan and
8985      optimize something away*/
8986   if (!is_adf_scan (s))
8987     s->page = 0;
8988 
8989   if (s->page > 0 && s->duplex_rear_valid) {
8990     DBG (1, "sane_start: virtual duplex rear data valid.\n");
8991     goto start_scan_end;
8992   }
8993 
8994   /* Check for paper during ADF scans and for sheetfed scanners. */
8995   if (is_adf_scan (s)) {
8996     status = media_check (s);
8997     if (status != SANE_STATUS_GOOD) {
8998       DBG (1, "sane_start: media_check failed: %s\n",
8999 	   sane_strstatus (status));
9000       return status;
9001     }
9002     else
9003       DBG (1, "sane_start: media_check ok\n");
9004   }
9005 
9006   /* Check the light early, to return to the GUI and notify the user. */
9007   if (s->prepared == SANE_FALSE) {
9008     if (dev->inquiry_light_control) {
9009       status = wait_4_light (s);
9010       if (status != SANE_STATUS_GOOD) {
9011         return status;
9012       }
9013     }
9014   }
9015 
9016   if (s->page > 0 && dev->inquiry_keeps_window) {
9017      DBG (1, "sane_start: Optimized set_window away.\n");
9018   }
9019   else
9020   {
9021     status = set_window (s);
9022     if (status != SANE_STATUS_GOOD) {
9023       DBG (1, "sane_start: set scan window command failed: %s\n",
9024 	   sane_strstatus (status));
9025       goto stop_scanner_and_return;
9026     }
9027     /* Re-check the light, as setting the window may have changed
9028      * which light is to be turned on. */
9029     if (s->prepared == SANE_FALSE && dev->inquiry_light_control) {
9030       status = wait_4_light (s);
9031       if (status != SANE_STATUS_GOOD) {
9032 	return status;
9033       }
9034     }
9035   }
9036 
9037 #ifdef DEBUG_TEST
9038   /* debug window size test ... */
9039   if (dev->inquiry_new_protocol)
9040     {
9041       size_t size = 16;
9042       uint8_t result[16];
9043 
9044       DBG (5, "sane_start: reading scanner window size\n");
9045 
9046       status = simple_read (s, 0x80, 0, &size, result);
9047 
9048       if (status != SANE_STATUS_GOOD) {
9049 	DBG (1, "sane_start: get pixel size command failed: %s\n",
9050 	     sane_strstatus (status));
9051 	goto stop_scanner_and_return;
9052       }
9053       debug_print_raw (5, "sane_start: pixel_size:", result, size);
9054       DBG (5, "sane_start: x-pixels: %d, y-pixels: %d\n",
9055 	   get_quad (&(result[0])), get_quad (&(result[4])));
9056     }
9057 #endif
9058 
9059   /* no calibration for ADF pages */
9060   if (s->page > 0) {
9061     DBG (1, "sane_start: optimized calibration away.\n");
9062     goto calib_end;
9063   }
9064 
9065   /* check whether the user enforces calibration */
9066   if (force_calibration) {
9067     DBG (1, "sane_start: calibration enforced in config!\n");
9068     goto calib;
9069   }
9070 
9071   /* Only perform the calibration for newer scanners - it is not needed
9072      for my Avision AV 630 - and also does not even work ... */
9073   if (!dev->inquiry_new_protocol) {
9074     DBG (1, "sane_start: old protocol no calibration needed!\n");
9075     goto calib_end;
9076   }
9077 
9078   if (!dev->inquiry_needs_calibration) {
9079     DBG (1, "sane_start: due to inquiry no calibration needed!\n");
9080     goto calib_end;
9081   }
9082 
9083   /* calibration allowed for this scanner? */
9084   if (dev->hw->feature_type & AV_NO_CALIB) {
9085     DBG (1, "sane_start: calibration disabled in device list!!\n");
9086     goto calib_end;
9087   }
9088 
9089   /* Not for film scanners, ... */
9090   if (dev->scanner_type == AV_FILM) {
9091     DBG (1, "sane_start: no calibration for film scanner!\n");
9092     goto calib_end;
9093   }
9094 
9095   /* check whether calibration is disabled by the user */
9096   if (disable_calibration) {
9097     DBG (1, "sane_start: calibration disabled in config - skipped!\n");
9098     goto calib_end;
9099   }
9100 
9101   /* R² reminder: We must not skip the calibration for ADF scans, some
9102      scanner (HP 53xx/74xx ASIC series) rely on a calibration data
9103      read (and will hang otherwise) */
9104 
9105  calib:
9106   status = normal_calibration (s);
9107 
9108   if (status != SANE_STATUS_GOOD) {
9109     DBG (1, "sane_start: perform calibration failed: %s\n",
9110 	 sane_strstatus (status));
9111 	goto stop_scanner_and_return;
9112   }
9113 
9114  calib_end:
9115 
9116   if (dev->inquiry_3x3_matrix && dev->inquiry_asic_type >= AV_ASIC_C6 &&
9117       s->page == 0)
9118   {
9119     status = send_3x3_matrix (s);
9120     if (status != SANE_STATUS_GOOD) {
9121       return status;
9122     }
9123   }
9124 
9125   /* check whether gamma-table is disabled by the user? */
9126   if (disable_gamma_table) {
9127     DBG (1, "sane_start: gamma-table disabled in config - skipped!\n");
9128     goto gamma_end;
9129   }
9130 
9131   if (dev->hw->feature_type & AV_NO_GAMMA) {
9132     DBG (1, "sane_start: gamma table skipped due to device-list!!\n");
9133     goto gamma_end;
9134   }
9135 
9136   if (s->page > 0 && dev->inquiry_keeps_gamma)
9137     DBG (1, "sane_start: Optimized send_gamma away.\n");
9138   else
9139   {
9140     status = send_gamma (s);
9141     if (status != SANE_STATUS_GOOD) {
9142       DBG (1, "sane_start: send gamma failed: %s\n",
9143 	   sane_strstatus (status));
9144       goto stop_scanner_and_return;
9145     }
9146   }
9147 
9148  gamma_end:
9149 
9150   if (dev->inquiry_tune_scan_length && is_adf_scan (s)) {
9151     status = send_tune_scan_length (s);
9152     if (status != SANE_STATUS_GOOD) {
9153       DBG (1, "sane_start: tune_scan_length command failed: %s\n",
9154 	   sane_strstatus (status));
9155       goto stop_scanner_and_return;
9156     }
9157   }
9158 
9159   /* if the device supports retrieving background raster data
9160      inquire the data no matter if the user/applications asks for
9161      it in order to use it for bottom padding */
9162   if (s->page == 0 && dev->inquiry_background_raster) {
9163     status = get_background_raster (s);
9164     if (status != SANE_STATUS_GOOD) {
9165       DBG (1, "sane_start: get background raster command failed: %s\n",
9166 	   sane_strstatus (status));
9167       goto stop_scanner_and_return;
9168     }
9169   }
9170 
9171   /* check film holder */
9172   if (dev->scanner_type == AV_FILM && dev->holder_type == 0xff) {
9173     DBG (1, "sane_start: no film holder or APS cassette!\n");
9174 
9175     /* Normally "go_home" is executed from the reader process,
9176        but as it will not start we have to reset things here */
9177     if (dev->inquiry_new_protocol) {
9178       status = object_position (s, AVISION_SCSI_OP_GO_HOME);
9179       if (status != SANE_STATUS_GOOD)
9180 	DBG (1, "sane_start: go home failed: %s\n",
9181 	     sane_strstatus (status));
9182     }
9183     goto stop_scanner_and_return;
9184   }
9185 
9186  start_scan_end:
9187 
9188   s->scanning = SANE_TRUE;
9189   s->page += 1; /* processing next page */
9190 
9191   if (pipe (fds) < 0) {
9192     return SANE_STATUS_IO_ERROR;
9193   }
9194 
9195   s->read_fds = fds[0];
9196   s->write_fds = fds[1];
9197 
9198   /* create reader routine as new process or thread */
9199   DBG (3, "sane_start: starting thread\n");
9200   s->reader_pid = sanei_thread_begin (reader_process, (void *) s);
9201 
9202   if (sanei_thread_is_forked()) {
9203     close (s->write_fds);
9204     s->write_fds = -1;
9205   }
9206 
9207   return SANE_STATUS_GOOD;
9208 
9209  stop_scanner_and_return:
9210 
9211   /* cancel the scan nicely */
9212   do_cancel (s);
9213 
9214   return status;
9215 }
9216 
9217 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)9218 sane_read (SANE_Handle handle, SANE_Byte* buf, SANE_Int max_len, SANE_Int* len)
9219 {
9220   Avision_Scanner* s = handle;
9221   ssize_t nread;
9222   *len = 0;
9223 
9224   DBG (8, "sane_read: max_len: %d\n", max_len);
9225 
9226   nread = read (s->read_fds, buf, max_len);
9227   if (nread > 0) {
9228     DBG (8, "sane_read: got %ld bytes\n", (long) nread);
9229   }
9230   else {
9231     DBG (3, "sane_read: got %ld bytes, err: %d %s\n", (long) nread, errno, strerror(errno));
9232   }
9233 
9234   if (!s->scanning)
9235     return SANE_STATUS_CANCELLED;
9236 
9237   if (nread < 0) {
9238     if (errno == EAGAIN) {
9239       return SANE_STATUS_GOOD;
9240     } else {
9241       do_cancel (s);
9242       return SANE_STATUS_IO_ERROR;
9243     }
9244   }
9245 
9246   *len = nread;
9247 
9248   /* if all data was passed through */
9249   if (nread == 0)
9250     return do_eof (s);
9251 
9252   return SANE_STATUS_GOOD;
9253 }
9254 
9255 void
sane_cancel(SANE_Handle handle)9256 sane_cancel (SANE_Handle handle)
9257 {
9258   Avision_Scanner* s = handle;
9259   DBG (3, "sane_cancel:\n");
9260 
9261   /* always do the housekeeping, e.g. flush batch scanner pages */
9262   do_cancel (s);
9263 }
9264 
9265 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)9266 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
9267 {
9268   Avision_Scanner* s = handle;
9269 
9270   DBG (3, "sane_set_io_mode:\n");
9271   if (!s->scanning) {
9272     DBG (3, "sane_set_io_mode: not yet scanning\n");
9273     return SANE_STATUS_INVAL;
9274   }
9275 
9276   if (fcntl (s->read_fds, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
9277     return SANE_STATUS_IO_ERROR;
9278 
9279   return SANE_STATUS_GOOD;
9280 }
9281 
9282 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)9283 sane_get_select_fd (SANE_Handle handle, SANE_Int* fd)
9284 {
9285   Avision_Scanner* s = handle;
9286 
9287   DBG (3, "sane_get_select_fd:\n");
9288 
9289   if (!s->scanning) {
9290     DBG (3, "sane_get_select_fd: not yet scanning\n");
9291     return SANE_STATUS_INVAL;
9292   }
9293 
9294   *fd = s->read_fds;
9295   return SANE_STATUS_GOOD;
9296 }
9297