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