• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = 1;
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   /*
3815    * Cope with ADF presence flag being present but the device *not* reporting
3816    * ADF capability. Maybe there are some devices that do that? [RL]
3817    *
3818    */
3819   dev->inquiry_adf_present = result [0];
3820 
3821   /*
3822    * Note: this feature_type check is a bit of a hack.
3823    * Only the HP Scanjet 8200 series supports this so it is code
3824    * specific to this family of scanners. [RL]
3825    *
3826    */
3827   if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX)
3828     {
3829       if (result[0] == 1)
3830         {
3831           dev->inquiry_duplex = 1;
3832           dev->inquiry_duplex_interlaced = 0;
3833         }
3834       else if (result[0] == 0 && result[2] != 0 && !skip_adf)
3835         {
3836           /* Sometimes the scanner will report that there is no ADF attached, yet
3837            * an ADF model number will still be reported.  This happens on the
3838            * HP8200 series and possibly others.  In this case we need to reset the
3839            * the adf and try reading it again.  Skip this if the configuration says
3840            * to do so, so that we don't fail out the scanner as being broken and
3841            * unsupported if there isn't actually an ADF present.
3842            *
3843            * Note further: Some models (like the ScanJet 8300) report that they have ADF
3844            * *capability* in the INQUIRY response but that doesn't necessarily mean that
3845            * an ADF is plugged in. In my case it has the lightbox accessory instead and
3846            * result[0] == FALSE.
3847            * Trying to reset the ADF 3 times is excessive and takes an unreasonable amount
3848            * of time on the 8300 with no ADF plugged in, so let's do it just once and if
3849            * it fails to report presence, then don't assume it is an error, just that
3850            * there is no ADF. [RL]
3851            *
3852            */
3853           if (!try)
3854             {
3855               DBG (
3856                   1,
3857                   "get_accessories_info: Maximum retries attempted, ADF unresponsive.\n");
3858               dev->inquiry_adf_present = SANE_FALSE;
3859               //return SANE_STATUS_UNSUPPORTED;
3860             }
3861           else
3862             {
3863               try--;
3864 
3865               DBG(3,
3866                   "get_accessories_info: Found ADF model number but the ADF-present flag is not set. "
3867                   "Trying to reset the ADF just in case it is there but unresponsive...\n");
3868               status = adf_reset (s);
3869               if (status != SANE_STATUS_GOOD)
3870                 {
3871                   DBG (3, "get_accessories_info: Failed to reset ADF: %s\n", sane_strstatus (status));
3872                   return status;
3873                 }
3874 
3875               DBG(1,"get_accessories_info: Waiting while ADF firmware resets...\n");
3876               sleep (3);
3877               status = wait_ready (&s->av_con, 1);
3878               if (status != SANE_STATUS_GOOD)
3879                 {
3880                   DBG (1, "get_accessories_info: wait_ready() failed: %s\n",
3881                        sane_strstatus (status));
3882                   return status;
3883                 }
3884               goto RETRY;
3885             }
3886         }
3887     }
3888 
3889   /* only honor a 1, some scanner without adapter set 0xff */
3890   if (result[1] == 1)
3891     dev->inquiry_light_box_present = 1;
3892 
3893   return SANE_STATUS_GOOD;
3894 }
3895 
3896 
3897 /* Returns a pointer to static char* strings or NULL for cancel (we do
3898    not want to start memcmp'ing for the cancel case). */
3899 static const char*
string_for_button(Avision_Scanner * s,uint8_t button)3900 string_for_button (Avision_Scanner* s, uint8_t button)
3901 {
3902   static char buffer [16];
3903   Avision_Device* dev = s->hw;
3904 
3905   /* dev->sane.model
3906      dev->inquiry_asic_type */
3907 
3908   if (dev->inquiry_buttons == 1)
3909     goto return_scan;
3910 
3911   /* simplex / duplex buttons */
3912   if (strcmp (dev->sane.vendor, "Xerox") == 0 ||
3913       strcmp (dev->sane.vendor, "Visioneer") == 0 ||
3914       strcmp (dev->sane.model, "AV121") == 0 ||
3915       strcmp (dev->sane.model, "AV122") == 0
3916       )
3917     {
3918       switch (button)
3919 	{
3920 	case 1: return "simplex";
3921 	case 2: return "duplex";
3922 	}
3923     }
3924 
3925   if (strcmp (dev->sane.model, "AV210C2") == 0 ||
3926       strcmp (dev->sane.model, "AV210D2+") == 0 ||
3927       strcmp (dev->sane.model, "AV220C2") == 0 ||
3928       strcmp (dev->sane.model, "AV610C2") == 0
3929       )
3930     {
3931       if (button == 1)
3932 	return NULL; /* cancel */
3933       else
3934 	goto return_scan;
3935     }
3936 
3937   /* those are unique, right now */
3938   if (strcmp (dev->sane.model, "AV610") == 0)
3939     {
3940       switch (button)
3941 	{
3942 	case 0: return "email";
3943 	case 1: return "copy";
3944 	case 2: return "scan";
3945 	}
3946     }
3947 
3948   /* last resort */
3949   snprintf (buffer, sizeof (buffer), "button%d", button);
3950   return buffer;
3951 
3952  return_scan:
3953   return "scan";
3954 }
3955 
3956 static SANE_Status
get_button_status(Avision_Scanner * s)3957 get_button_status (Avision_Scanner* s)
3958 {
3959   Avision_Device* dev = s->hw;
3960 
3961   /* read stuff */
3962   struct command_read rcmd;
3963   size_t size;
3964   SANE_Status status;
3965   /* was only 6 in an old SPEC - maybe we need a feature override :-( -ReneR */
3966   struct {
3967      uint8_t press_state;
3968      uint8_t buttons[5];
3969      uint8_t display; /* AV220 et.al. 7 segment LED display */
3970      uint8_t reserved[9];
3971   } result;
3972 
3973   unsigned int i;
3974 
3975   DBG (3, "get_button_status:\n");
3976 
3977   size = sizeof (result);
3978 
3979   /* AV220 et.al. */
3980   if (! (dev->hw->feature_type & AV_INT_BUTTON))
3981     {
3982       memset (&rcmd, 0, sizeof (rcmd));
3983       rcmd.opc = AVISION_SCSI_READ;
3984 
3985       rcmd.datatypecode = AVISION_DATATYPECODE_BUTTON_STATUS; /* button status */
3986       set_double (rcmd.datatypequal, dev->data_dq);
3987       set_triple (rcmd.transferlen, size);
3988 
3989       status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0,
3990 			    (uint8_t*)&result, &size);
3991       if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
3992 	status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
3993 	DBG (1, "get_button_status: read failed (%s)\n", sane_strstatus (status));
3994 	return status;
3995       }
3996     }
3997   else
3998     {
3999       /* only try to read the first 8 bytes ...*/
4000       size = 8;
4001 
4002       /* no SCSI equivalent */
4003       /* either there was a button press and this completes quickly
4004          or there is no point waiting for a future press */
4005       sanei_usb_set_timeout (100); /* 10th of a second */
4006       DBG (5, "==> (interrupt read) going down ...\n");
4007       status = sanei_usb_read_int (s->av_con.usb_dn, (uint8_t*)&result,
4008 				   &size);
4009       DBG (5, "==> (interrupt read) got: %ld\n", (long)size);
4010 
4011       if (status != SANE_STATUS_GOOD) {
4012 	DBG (1, "get_button_status: interrupt read failed (%s)\n",
4013 	     sane_strstatus (status));
4014 	return SANE_STATUS_GOOD;
4015       }
4016 
4017       if (size < sizeof (result))
4018 	memset ((char*)result.buttons + size, 0, sizeof (result) - size);
4019 
4020       /* hack to fill in meaningful values for the AV 210 / 610 and
4021 	 under some conditions the AV 220 */
4022       if (size == 1) { /* AV 210, AV 610 */
4023 	DBG (1, "get_button_status: just one byte, filling the rest\n");
4024 
4025 	if (result.press_state > 0) {
4026 	  debug_print_raw (6, "get_button_status: raw data\n",
4027 			   (uint8_t*)&result, size);
4028 	  result.buttons[0] = result.press_state;
4029 	  result.press_state = 0x80 | 1;
4030 	  size = 2;
4031 	}
4032 	else /* nothing pressed */
4033 	  return SANE_STATUS_GOOD;
4034       }
4035       else if (size >= 8 && result.press_state == 0) { /* AV 220 */
4036 
4037 	debug_print_raw (6, "get_button_status: raw data\n",
4038 		   (uint8_t*)&result, size);
4039 
4040 	DBG (1, "get_button_status: zero buttons  - filling values ...\n");
4041 
4042 	/* simulate button press of the last button ... */
4043 	result.press_state = 0x80 | 1;
4044 	result.buttons[0] = (uint8_t) dev->inquiry_buttons; /* 1 based */
4045       }
4046     }
4047 
4048   debug_print_raw (6, "get_button_status: raw data\n",
4049 		   (uint8_t*)&result, size);
4050 
4051   DBG (3, "get_button_status: [0]  Button status: %x\n", result.press_state);
4052   for (i = 0; i < 5; ++i)
4053     DBG (3, "get_button_status: [%d]  Button number %d: %x\n", i+1, i,
4054 	 result.buttons[i]);
4055   DBG (3, "get_button_status: [7]  Display: %d\n", result.display);
4056 
4057   {
4058     char* message_begin = s->val[OPT_MESSAGE].s;
4059     char* message_end = s->val[OPT_MESSAGE].s + s->opt[OPT_MESSAGE].size;
4060     char* message = message_begin;
4061 
4062 #define add_token(format,value) do {				     \
4063       int n = snprintf (message, (size_t) (message_end - message), "%s" format, \
4064                         message == message_begin ? "" : ":", value); \
4065       message += n > 0 ? n : 0;					     \
4066     } while (0)
4067 
4068     if (result.display > 0)
4069       add_token ("%d", result.display);
4070 
4071     if (result.press_state >> 7) /* AV220 et.al. bit 6 is long/short press? */
4072       {
4073 
4074 	const unsigned int buttons_pressed = result.press_state & 0x7F;
4075 	DBG (3, "get_button_status: %d button(s) pressed\n", buttons_pressed);
4076 
4077 	/* reset the hardware button status */
4078 	if (! (dev->hw->feature_type & AV_INT_BUTTON))
4079 	  {
4080 	    struct command_send scmd;
4081 	    uint8_t button_reset = 1;
4082 
4083 	    DBG (3, "get_button_status: resetting status\n");
4084 
4085 	    memset (&scmd, 0, sizeof (scmd));
4086 
4087 	    scmd.opc = AVISION_SCSI_SEND;
4088 	    scmd.datatypecode = AVISION_DATATYPECODE_BUTTON_STATUS; /* button control */
4089 	    set_double (scmd.datatypequal, dev->data_dq);
4090 	    set_triple (scmd.transferlen, size);
4091 
4092 	    status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
4093 				  &button_reset, sizeof (button_reset), 0, 0);
4094 
4095 	    if (status != SANE_STATUS_GOOD) {
4096 	      DBG (1, "get_button_status: send failed (%s)\n",
4097 		   sane_strstatus (status));
4098 	      return status;
4099 	    }
4100 	  }
4101 
4102 	for (i = 0; i < buttons_pressed; ++i) {
4103 	  const uint8_t button = result.buttons[i] - 1; /* 1 based ... */
4104 	  DBG (3, "get_button_status: button %d pressed\n", button);
4105 	  if (button >= dev->inquiry_buttons) {
4106 	    DBG (1, "get_button_status: button %d not allocated as not indicated in inquiry\n",
4107 		 button);
4108 	  }
4109 	  else {
4110 	    const char* label = string_for_button (s, button);
4111 	    if (label)
4112 	      add_token ("%s", label);
4113 	    else
4114 	      return SANE_STATUS_CANCELLED;
4115 	  }
4116 	}
4117       }
4118     else
4119       DBG (3, "get_button_status: no button pressed\n");
4120   }
4121 
4122   return SANE_STATUS_GOOD;
4123 #undef add_token
4124 }
4125 
4126 static SANE_Status
get_frame_info(Avision_Scanner * s)4127 get_frame_info (Avision_Scanner* s)
4128 {
4129   Avision_Device* dev = s->hw;
4130 
4131   /* read stuff */
4132   struct command_read rcmd;
4133   size_t size;
4134   SANE_Status status;
4135   uint8_t result[8];
4136   size_t i;
4137 
4138   DBG (3, "get_frame_info:\n");
4139 
4140   size = sizeof (result);
4141 
4142   memset (&rcmd, 0, sizeof (rcmd));
4143   rcmd.opc = AVISION_SCSI_READ;
4144 
4145   rcmd.datatypecode = AVISION_DATATYPECODE_FILM_HOLDER_SENSE; /* film holder sense */
4146   set_double (rcmd.datatypequal, dev->data_dq);
4147   set_triple (rcmd.transferlen, size);
4148 
4149   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
4150   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
4151     status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
4152     DBG (1, "get_frame_info: read failed (%s)\n", sane_strstatus (status));
4153     return (status);
4154   }
4155 
4156   debug_print_raw (6, "get_frame_info: raw data\n", result, size);
4157 
4158   DBG (3, "get_frame_info: [0]  Holder type: %s\n",
4159        (result[0]==1)?"APS":
4160        (result[0]==2)?"Film holder (35mm)":
4161        (result[0]==3)?"Slide holder":
4162        (result[0]==0xff)?"Empty":"unknown");
4163   DBG (3, "get_frame_info: [1]  Current frame number: %d\n", result[1]);
4164   DBG (3, "get_frame_info: [2]  Frame amount: %d\n", result[2]);
4165   DBG (3, "get_frame_info: [3]  Mode: %s\n", BIT(result[3],4)?"APS":"Not APS");
4166   DBG (3, "get_frame_info: [3]  Exposures (if APS): %s\n",
4167        ((i=(size_t) (BIT(result[3],3)<<1)+BIT(result[2],2))==0)?"Unknown":
4168        (i==1)?"15":(i==2)?"25":"40");
4169   DBG (3, "get_frame_info: [3]  Film Type (if APS): %s\n",
4170        ((i=(size_t) (BIT(result[1],3)<<1)+BIT(result[0],2))==0)?"Unknown":
4171        (i==1)?"B&W Negative":(i==2)?"Color slide":"Color Negative");
4172 
4173   dev->holder_type = result[0];
4174   dev->current_frame = result[1];
4175 
4176   dev->frame_range.min = 1;
4177   dev->frame_range.quant = 1;
4178 
4179   if (result[0] != 0xff)
4180     dev->frame_range.max = result[2];
4181   else
4182     dev->frame_range.max = 1;
4183 
4184   return SANE_STATUS_GOOD;
4185 }
4186 
4187 static SANE_Status
get_duplex_info(Avision_Scanner * s)4188 get_duplex_info (Avision_Scanner* s)
4189 {
4190   Avision_Device* dev = s->hw;
4191 
4192   /* read stuff */
4193   struct command_read rcmd;
4194 
4195   struct {
4196      uint8_t mode;
4197      uint8_t color_line_difference[2];
4198      uint8_t gray_line_difference[2];
4199      uint8_t lineart_line_difference[2];
4200      uint8_t image_info;
4201   } result;
4202 
4203   size_t size;
4204   SANE_Status status;
4205 
4206   DBG (3, "get_duplex_info:\n");
4207 
4208   size = sizeof (result);
4209 
4210   memset (&rcmd, 0, sizeof (rcmd));
4211   rcmd.opc = AVISION_SCSI_READ;
4212 
4213   rcmd.datatypecode = AVISION_DATATYPECODE_READ_DUPLEX_INFO; /* read duplex info */
4214   set_double (rcmd.datatypequal, dev->data_dq);
4215   set_triple (rcmd.transferlen, size);
4216 
4217   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0,
4218 			&result, &size);
4219   if (status != SANE_STATUS_GOOD || size != sizeof (result)) {
4220     status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
4221     DBG (1, "get_duplex_info: read failed (%s)\n", sane_strstatus (status));
4222     return (status);
4223   }
4224 
4225   debug_print_raw (6, "get_duplex_info: raw data\n", (uint8_t*)&result, size);
4226 
4227   DBG (3, "get_duplex_info: [0]    Mode: %s%s\n",
4228        BIT(result.mode,0)?"MERGED_PAGES":"",
4229        BIT(result.mode,1)?"2ND_PAGE_FOLLOWS":"");
4230   DBG (3, "get_duplex_info: [1-2]  Color line difference: %d\n",
4231        get_double(result.color_line_difference));
4232   DBG (3, "get_duplex_info: [3-4]  Gray line difference: %d\n",
4233        get_double(result.gray_line_difference));
4234   DBG (3, "get_duplex_info: [5-6]  Lineart line difference: %d\n",
4235        get_double(result.lineart_line_difference));
4236   /* isn't this supposed to be result.info ?!? */
4237   DBG (3, "get_duplex_info: [7]    Mode: %s%s%s%s\n",
4238        BIT(result.image_info,0)?" FLATBED_BGR":" FLATBED_RGB",
4239        BIT(result.image_info,1)?" ADF_BGR":" ADF_RGB",
4240        BIT(result.image_info,2)?" FLATBED_NEEDS_MIRROR_IMAGE":"",
4241        BIT(result.image_info,3)?" ADF_NEEDS_MIRROR_IMAGE":"");
4242 
4243   return SANE_STATUS_GOOD;
4244 }
4245 
4246 static SANE_Status
set_frame(Avision_Scanner * s,SANE_Word frame)4247 set_frame (Avision_Scanner* s, SANE_Word frame)
4248 {
4249   struct {
4250     struct command_send cmd;
4251     uint8_t data[8];
4252   } scmd;
4253 
4254   Avision_Device* dev = s->hw;
4255   SANE_Status status;
4256 
4257   DBG (3, "set_frame: request frame %d\n", frame);
4258 
4259   /* Better check the current status of the film holder, because it
4260      can be changed between scans. */
4261   status = get_frame_info (s);
4262   if (status != SANE_STATUS_GOOD)
4263     return status;
4264 
4265   /* No film holder? */
4266   if (dev->holder_type == 0xff) {
4267     DBG (1, "set_frame: No film holder!!\n");
4268     return SANE_STATUS_INVAL;
4269   }
4270 
4271   /* Requesting frame 0xff indicates eject/rewind */
4272   if (frame != 0xff && (frame < 1 || frame > dev->frame_range.max) ) {
4273     DBG (1, "set_frame: Illegal frame (%d) requested (min=1, max=%d)\n",
4274 	 frame, dev->frame_range.max);
4275     return SANE_STATUS_INVAL;
4276   }
4277 
4278   memset (&scmd, 0, sizeof (scmd));
4279   scmd.cmd.opc = AVISION_SCSI_SEND;
4280   scmd.cmd.datatypecode = AVISION_DATATYPECODE_FILM_HOLDER_SENSE; /* send film holder "sense" */
4281   set_double (scmd.cmd.datatypequal, dev->data_dq);
4282   set_triple (scmd.cmd.transferlen, sizeof (scmd.data) );
4283 
4284   scmd.data[0] = (uint8_t) dev->holder_type;
4285   scmd.data[1] = (uint8_t) frame;
4286 
4287   status = avision_cmd (&s->av_con, &scmd.cmd, sizeof (scmd.cmd),
4288 			&scmd.data, sizeof (scmd.data), 0, 0);
4289   if (status != SANE_STATUS_GOOD) {
4290     DBG (1, "set_frame: send_data (%s)\n", sane_strstatus (status));
4291   }
4292 
4293   return status;
4294 }
4295 
4296 static SANE_Status
attach(SANE_String_Const devname,Avision_ConnectionType con_type,Avision_Device ** devp)4297 attach (SANE_String_Const devname, Avision_ConnectionType con_type,
4298         Avision_Device** devp)
4299 {
4300   uint8_t result [AVISION_INQUIRY_SIZE_MAX];
4301   int model_num;
4302 
4303   Avision_Device* dev;
4304   SANE_Status status;
4305 
4306   Avision_Connection av_con;
4307 
4308   char mfg [9];
4309   char model [17];
4310   char rev [5];
4311 
4312   unsigned int i;
4313   char* s;
4314   SANE_Bool found;
4315 
4316   DBG (3, "attach:\n");
4317   memset (result, 0, sizeof(result));
4318 
4319   for (dev = first_dev; dev; dev = dev->next)
4320     if (strcmp (dev->sane.name, devname) == 0) {
4321       if (devp)
4322 	*devp = dev;
4323       return SANE_STATUS_GOOD;
4324     }
4325 
4326   av_con.connection_type = con_type;
4327   if (av_con.connection_type == AV_USB)
4328     av_con.usb_status = AVISION_USB_UNTESTED_STATUS;
4329 
4330   /* set known USB status type */
4331   if (attaching_hw && (attaching_hw->feature_type & AV_INT_STATUS))
4332     av_con.usb_status = AVISION_USB_INT_STATUS;
4333 
4334   DBG (3, "attach: opening %s\n", devname);
4335   status = avision_open (devname, &av_con, sense_handler, 0);
4336   if (status != SANE_STATUS_GOOD) {
4337     DBG (1, "attach: open failed (%s)\n", sane_strstatus (status));
4338     return SANE_STATUS_INVAL;
4339   }
4340 
4341   /* first: get the standard inquiry? */
4342   status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1);
4343   if (status != SANE_STATUS_GOOD) {
4344     DBG (1, "attach: 1st inquiry failed (%s)\n", sane_strstatus (status));
4345     return status;
4346   }
4347 
4348   /* copy string information - and zero terminate them c-style */
4349   memcpy (&mfg, result + 8, 8);
4350   mfg [8] = 0;
4351   memcpy (&model, result + 16, 16);
4352   model [16] = 0;
4353   memcpy (&rev, result + 32, 4);
4354   rev [4] = 0;
4355 
4356   /* shorten strings (-1 for last index
4357      -1 for last 0; >0 because one char at least) */
4358   for (i = sizeof (mfg) - 2; i > 0; i--) {
4359     if (mfg[i] == 0x20)
4360       mfg[i] = 0;
4361     else
4362       break;
4363   }
4364   for (i = sizeof (model) - 2; i > 0; i--) {
4365     if (model[i] == 0x20)
4366       model[i] = 0;
4367     else
4368       break;
4369   }
4370 
4371   DBG (1, "attach: Inquiry gives mfg=%s, model=%s, product revision=%s.\n",
4372        mfg, model, rev);
4373 
4374   model_num = 0;
4375   found = 0;
4376 
4377   /*
4378    * Search for a matching device in the device list.
4379    * Primarily we need two matches for SCSI devices.
4380    * However, multiple USB device entries share the same
4381    * SCSI info. For USB devices, we will also do a mandatory
4382    * USB Product/Vendor check to pick the right one. Otherwise
4383    * at the very least the device name is incorrect.
4384    *
4385    */
4386   SANE_Word usb_vendor = 0;
4387   SANE_Word usb_product = 0;
4388 
4389   if (con_type == AV_USB)
4390     {
4391       status = sanei_usb_get_vendor_product_byname (devname, &usb_vendor, &usb_product);
4392       if (status != SANE_STATUS_GOOD)
4393         {
4394           DBG (0, "attach: Could not retrieve USB vendor nor product for USB device.\n");
4395           status = SANE_STATUS_INVAL;
4396           goto close_scanner_and_return;
4397         }
4398     }
4399 
4400   /* while not at at end of list NULL terminator */
4401   while (Avision_Device_List[model_num].real_mfg != NULL
4402       || Avision_Device_List[model_num].scsi_mfg != NULL)
4403     {
4404       int matches = 0, match_count = 0; /* count number of matches */
4405       DBG (1, "attach: Checking model: %d\n", model_num);
4406 
4407       if (Avision_Device_List[model_num].scsi_mfg)
4408         {
4409           ++match_count;
4410           if (strcmp (mfg, Avision_Device_List[model_num].scsi_mfg) == 0)
4411             ++matches;
4412         }
4413       if (Avision_Device_List[model_num].scsi_model)
4414         {
4415           ++match_count;
4416           if (strcmp (model, Avision_Device_List[model_num].scsi_model) == 0)
4417             ++matches;
4418         }
4419 
4420       /*
4421        * Must match on USB vendor product also for USB devices.
4422        * We will *always* know the vendor and product for USB devices.
4423        *
4424        */
4425       if (con_type == AV_USB)
4426         {
4427           ++match_count;
4428           if ((Avision_Device_List[model_num].usb_product == usb_product)
4429               && (Avision_Device_List[model_num].usb_vendor == usb_vendor))
4430             {
4431               ++matches;
4432             }
4433         }
4434 
4435       /* we need 2 matches (mfg, model) for SCSI entries, or the ones available
4436        for "we know what we are looking for" USB entries */
4437       if ((attaching_hw == &(Avision_Device_List[model_num]))
4438           && (matches == match_count))
4439         {
4440           DBG (
4441               1,
4442               "attach: Scanner matched entry: %d: \"%s\", \"%s\", 0x%.4x, 0x%.4x\n",
4443               model_num, Avision_Device_List[model_num].scsi_mfg,
4444               Avision_Device_List[model_num].scsi_model,
4445               Avision_Device_List[model_num].usb_vendor,
4446               Avision_Device_List[model_num].usb_product);
4447           found = 1;
4448           break;
4449         }
4450       ++model_num;
4451     }
4452 
4453   if (!found) {
4454     DBG (0, "attach: \"%s\" - \"%s\" not yet in whitelist!\n", mfg, model);
4455     DBG (0, "attach: You might want to report this output.\n");
4456     DBG (0, "attach: To: rene@exactcode.de (the Avision backend author)\n");
4457 
4458     status = SANE_STATUS_INVAL;
4459     goto close_scanner_and_return;
4460   }
4461 
4462   /* second: maybe ask for the firmware status and flash ram info */
4463   if (Avision_Device_List [model_num].feature_type & AV_FIRMWARE)
4464   {
4465       DBG (3, "attach: reading firmware status\n");
4466       status = get_firmware_status (&av_con);
4467       if (status != SANE_STATUS_GOOD) {
4468 	DBG (1, "attach: get firmware status failed (%s)\n",
4469 	     sane_strstatus (status));
4470 	goto close_scanner_and_return;
4471       }
4472 
4473       DBG (3, "attach: reading flash ram info\n");
4474       status = get_flash_ram_info (&av_con);
4475       if (status != SANE_STATUS_GOOD) {
4476 	DBG (1, "attach: get flash ram info failed (%s)\n",
4477 	     sane_strstatus (status));
4478 	goto close_scanner_and_return;
4479       }
4480 
4481 #ifdef FIRMWARE_DATABASE_INCLUDED
4482       /* Send new NV-RAM (firmware) data */
4483       status = send_nvram_data (&av_con);
4484       if (status != SANE_STATUS_GOOD)
4485 	goto close_scanner_and_return;
4486 #endif
4487   }
4488 
4489   /* third: get the extended Avision inquiry */
4490   status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1);
4491   if (status != SANE_STATUS_GOOD) {
4492     DBG (1, "attach: avision v1 inquiry failed (%s)\n", sane_strstatus (status));
4493     goto close_scanner_and_return;
4494   }
4495 
4496   dev = malloc (sizeof (*dev));
4497   if (!dev) {
4498     status = SANE_STATUS_NO_MEM;
4499     goto close_scanner_and_return;
4500   }
4501 
4502   memset (dev, 0, sizeof (*dev));
4503 
4504   dev->hw = &Avision_Device_List[model_num];
4505 
4506   dev->sane.name   = strdup (devname);
4507   dev->sane.vendor = dev->hw->real_mfg   ? dev->hw->real_mfg   : strdup (mfg);
4508   dev->sane.model  = dev->hw->real_model ? dev->hw->real_model : strdup (model);
4509   dev->connection.connection_type = av_con.connection_type;
4510   dev->connection.usb_status = av_con.usb_status;
4511 
4512   /* and finally Avision even extended this one later on
4513      the AV220C2 does not grok this */
4514   dev->inquiry_asic_type = (int) result[91];
4515   if (dev->inquiry_asic_type == AV_ASIC_C6)
4516     {
4517       status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V2);
4518       if (status != SANE_STATUS_GOOD) {
4519 	DBG (1, "attach: avision v2 inquiry failed (%s)\n", sane_strstatus (status));
4520 	goto close_scanner_and_return;
4521       }
4522     }
4523 
4524   debug_print_raw (6, "attach: raw data:\n", result, sizeof (result) );
4525 
4526   DBG (3, "attach: [8-15]  Vendor id.:      '%8.8s'\n", result+8);
4527   DBG (3, "attach: [16-31] Product id.:     '%16.16s'\n", result+16);
4528   DBG (3, "attach: [32-35] Product rev.:    '%4.4s'\n", result+32);
4529 
4530   i = (result[36] >> 4) & 0x7;
4531   switch (result[36] & 0x07) {
4532   case 0:
4533     s = " RGB"; break;
4534   case 1:
4535     s = " BGR"; break;
4536   default:
4537     s = " unknown (RESERVED)";
4538   }
4539   DBG (3, "attach: [36]    Bitfield:%s%s%s%s%s%s%s color plane\n",
4540        BIT(result[36],7)?" ADF":"",
4541        (i==0)?" B&W only":"",
4542        BIT(i, 1)?" 3-pass color":"",
4543        BIT(i, 2)?" 1-pass color":"",
4544        BIT(i, 2) && BIT(i, 0) ?" 1-pass color (ScanPartner only)":"",
4545        BIT(result[36],3)?" IS_NOT_FLATBED":"",
4546        s);
4547 
4548   DBG (3, "attach: [37]    Optical res.:    %d00 dpi\n", result[37]);
4549   DBG (3, "attach: [38]    Maximum res.:    %d00 dpi\n", result[38]);
4550 
4551   DBG (3, "attach: [39]    Bitfield1:%s%s%s%s%s%s\n",
4552        BIT(result[39],7)?" TRANS":"",
4553        BIT(result[39],6)?" Q_SCAN":"",
4554        BIT(result[39],5)?" EXTENDED_RES":"",
4555        BIT(result[39],4)?" SUPPORTS_CALIB":"",
4556        BIT(result[39],2)?" NEW_PROTOCOL":"",
4557        (result[39] & 0x03) == 0x03 ? " AVISION":" OEM");
4558 
4559   DBG (3, "attach: [40-41] X res. in gray:  %d dpi\n",
4560        get_double ( &(result[40]) ));
4561   DBG (3, "attach: [42-43] Y res. in gray:  %d dpi\n",
4562        get_double ( &(result[42]) ));
4563   DBG (3, "attach: [44-45] X res. in color: %d dpi\n",
4564        get_double ( &(result[44]) ));
4565   DBG (3, "attach: [46-47] Y res. in color: %d dpi\n",
4566        get_double ( &(result[46]) ));
4567   DBG (3, "attach: [48-49] USB max read:    %d\n",
4568 get_double ( &(result[48] ) ));
4569 
4570   DBG (3, "attach: [50]    ESA1:%s%s%s%s%s%s%s%s\n",
4571        BIT(result[50],7)?" LIGHT_CONTROL":"",
4572        BIT(result[50],6)?" BUTTON_CONTROL":"",
4573        BIT(result[50],5)?" NEED_SW_COLORPACK":"",
4574        BIT(result[50],4)?" SW_CALIB":"",
4575        BIT(result[50],3)?" NEED_SW_GAMMA":"",
4576        BIT(result[50],2)?" KEEPS_GAMMA":"",
4577        BIT(result[50],1)?" KEEPS_WINDOW_CMD":"",
4578        BIT(result[50],0)?" XYRES_DIFFERENT":"");
4579   DBG (3, "attach: [51]    ESA2:%s%s%s%s%s%s%s%s\n",
4580        BIT(result[51],7)?" EXPOSURE_CTRL":"",
4581        BIT(result[51],6)?" NEED_SW_TRIGGER_CAL":"",
4582        BIT(result[51],5)?" NEED_WHITE_PAPER_CALIB":"",
4583        BIT(result[51],4)?" SUPPORTS_QUALITY_SPEED_CAL":"",
4584        BIT(result[51],3)?" NEED_TRANSP_CAL":"",
4585        BIT(result[51],2)?" HAS_PUSH_BUTTON":"",
4586        BIT(result[51],1)?" NEW_CAL_METHOD_3x3_MATRIX_(NO_GAMMA_TABLE)":"",
4587        BIT(result[51],0)?" ADF_MIRRORS_IMAGE":"");
4588   DBG (3, "attach: [52]    ESA3:%s%s%s%s%s%s%s%s\n",
4589        BIT(result[52],7)?" GRAY_WHITE":"",
4590        BIT(result[52],6)?" SUPPORTS_GAIN_CONTROL":"",
4591        BIT(result[52],5)?" SUPPORTS_TET":"", /* "Text Enhanced Technology" */
4592        BIT(result[52],4)?" 3x3COL_TABLE":"",
4593        BIT(result[52],3)?" 1x3FILTER":"",
4594        BIT(result[52],2)?" INDEX_COLOR":"",
4595        BIT(result[52],1)?" POWER_SAVING_TIMER":"",
4596        BIT(result[52],0)?" NVM_DATA_REC":"");
4597 
4598   /* print some more scanner features/params */
4599   DBG (3, "attach: [53]    line difference (software color pack): %d\n", result[53]);
4600   DBG (3, "attach: [54]    color mode pixel boundary: %d\n", result[54]);
4601   DBG (3, "attach: [55]    gray mode pixel boundary: %d\n", result[55]);
4602   DBG (3, "attach: [56]    4bit gray mode pixel boundary: %d\n", result[56]);
4603   DBG (3, "attach: [57]    lineart mode pixel boundary: %d\n", result[57]);
4604   DBG (3, "attach: [58]    halftone mode pixel boundary: %d\n", result[58]);
4605   DBG (3, "attach: [59]    error-diffusion mode pixel boundary: %d\n", result[59]);
4606 
4607   DBG (3, "attach: [60]    channels per pixel:%s%s%s\n",
4608        BIT(result[60],7)?" 1":"",
4609        BIT(result[60],6)?" 3":"",
4610        (result[60] & 0x3F) != 0 ? " RESERVED":"");
4611 
4612   DBG (3, "attach: [61]    bits per channel:%s%s%s%s%s%s%s\n",
4613        BIT(result[61],7)?" 1":"",
4614        BIT(result[61],6)?" 4":"",
4615        BIT(result[61],5)?" 6":"",
4616        BIT(result[61],4)?" 8":"",
4617        BIT(result[61],3)?" 10":"",
4618        BIT(result[61],2)?" 12":"",
4619        BIT(result[61],1)?" 16":"");
4620 
4621   DBG (3, "attach: [62]    scanner type:%s%s%s%s%s%s\n",
4622        BIT(result[62],7)?" Flatbed":"",
4623        BIT(result[62],6)?" Roller (ADF)":"",
4624        BIT(result[62],5)?" Flatbed (ADF/Lightbox)":"",
4625        BIT(result[62],4)?" Roller":"", /* does not feed multiple pages, AV25 */
4626        BIT(result[62],3)?" Film scanner":"",
4627        BIT(result[62],2)?" Duplex":"");
4628 
4629   DBG (3, "attach: [75-76] Max shading target : %x\n",
4630        get_double ( &(result[75]) ));
4631 
4632   DBG (3, "attach: [77-78] Max X of transparency: %d dots * base_dpi\n",
4633        get_double ( &(result[77]) ));
4634   DBG (3, "attach: [79-80] Max Y of transparency: %d dots * base_dpi\n",
4635        get_double ( &(result[79]) ));
4636 
4637   DBG (3, "attach: [81-82] Max X of flatbed:      %d dots * base_dpi\n",
4638        get_double ( &(result[81]) ));
4639   DBG (3, "attach: [83-84] Max Y of flatbed:      %d dots * base_dpi\n",
4640        get_double ( &(result[83]) ));
4641 
4642   DBG (3, "attach: [85-86] Max X of ADF:          %d dots * base_dpi\n",
4643        get_double ( &(result[85]) ));
4644   DBG (3, "attach: [87-88] Max Y of ADF:          %d dots * base_dpi\n",
4645        get_double ( &(result[87]) )); /* 0xFFFF means unlimited length */
4646 
4647   DBG (3, "attach: [89-90] Res. in Ex. mode:      %d dpi\n",
4648        get_double ( &(result[89]) ));
4649 
4650   DBG (3, "attach: [91]    ASIC:     %d\n", result[91]);
4651 
4652   DBG (3, "attach: [92]    Buttons:  %d\n", result[92]);
4653 
4654   DBG (3, "attach: [93]    ESA4:%s%s%s%s%s%s%s%s\n",
4655        BIT(result[93],7)?" SUPPORTS_ACCESSORIES_DETECT":"",
4656        BIT(result[93],6)?" ADF_IS_BGR_ORDERED":"",
4657        BIT(result[93],5)?" NO_SINGLE_CHANNEL_GRAY_MODE":"",
4658        BIT(result[93],4)?" SUPPORTS_FLASH_UPDATE":"",
4659        BIT(result[93],3)?" SUPPORTS_ASIC_UPDATE":"",
4660        BIT(result[93],2)?" SUPPORTS_LIGHT_DETECT":"",
4661        BIT(result[93],1)?" SUPPORTS_READ_PRNU_DATA":"",
4662        BIT(result[93],0)?" FLATBED_MIRRORS_IMAGE":"");
4663 
4664   DBG (3, "attach: [94]    ESA5:%s%s%s%s%s%s%s%s\n",
4665        BIT(result[94],7)?" IGNORE_LINE_DIFFERENCE_FOR_ADF":"",
4666        BIT(result[94],6)?" NEEDS_SW_LINE_COLOR_PACK":"",
4667        BIT(result[94],5)?" SUPPORTS_DUPLEX_SCAN":"",
4668        BIT(result[94],4)?" INTERLACED_DUPLEX_SCAN":"",
4669        BIT(result[94],3)?" SUPPORTS_TWO_MODE_ADF_SCANS":"",
4670        BIT(result[94],2)?" SUPPORTS_TUNE_SCAN_LENGTH":"",
4671        BIT(result[94],1)?" SUPPORTS_SWITCH_STRIP_FOR_DESKEW":"", /* Kodak i80 only */
4672        BIT(result[94],0)?" SEARCHES_LEADING_SIDE_EDGE_BY_FIRMWARE":"");
4673 
4674   DBG (3, "attach: [95]    ESA6:%s%s%s%s%s%s%s%s\n",
4675        BIT(result[95],7)?" SUPPORTS_PAPER_SIZE_AUTO_DETECTION":"",
4676        BIT(result[95],6)?" SUPPORTS_DO_HOUSEKEEPING":"", /* Kodak i80 only */
4677        BIT(result[95],5)?" SUPPORTS_PAPER_LENGTH_SETTING":"", /* AV220, Kodak */
4678        BIT(result[95],4)?" SUPPORTS_PRE_GAMMA_LINEAR_CORRECTION":"",
4679        BIT(result[95],3)?" SUPPORTS_PREFEEDING":"", /*  OKI S9800 */
4680        BIT(result[95],2)?" SUPPORTS_GET_BACKGROUND_RASTER":"", /* AV220 et.al. */
4681        BIT(result[95],1)?" SUPPORTS_NVRAM_RESET":"",
4682        BIT(result[95],0)?" SUPPORTS_BATCH_SCAN":"");
4683 
4684   DBG (3, "attach: [128]    ESA7:%s%s%s%s%s%s%s%s\n",
4685        BIT(result[128],7)?" SUPPORTS_ADF_CONTINUOUS":"",
4686        BIT(result[128],6)?" SUPPORTS_YCbCr_COLOR":"",
4687        BIT(result[128],5)?" SUPPORTS_ADF_3PASS":"",
4688        BIT(result[128],4)?" SUPPORTS_TUNE_SCAN_LENGTH_HORIZ":"",
4689        BIT(result[128],3)?" SUPPORTS_READ_WRITE_ABILITY_PARAMETER":"",
4690        BIT(result[128],2)?" SUPPORTS_JOB_CONTROL":"",
4691        BIT(result[128],1)?" SUPPORTS_INF_LENGTH":"",
4692        BIT(result[128],0)?" ULTRA_SONIC_DOUBLE_FEED_DETECTION":"");
4693 
4694   DBG (3, "attach: [129]    YCbCr:%s%s%s%s%s%s%s%s\n",
4695        BIT(result[129],7)?" YCC4:2:0":"",
4696        BIT(result[129],6)?" YCC(profile2)":"",
4697        BIT(result[129],5)?" YCC(profile3)":"",
4698        BIT(result[129],4)?" YCC(profile4)":"",
4699        BIT(result[129],3)?" JPEG(profile1)":"",
4700        BIT(result[129],2)?" JPEG(profile2)":"",
4701        BIT(result[129],1)?" JPEG(profile3)":"",
4702        BIT(result[129],0)?" JPEG(profile4)":"");
4703 
4704   /* I have no idea how film scanner could reliably be detected -ReneR */
4705   if (dev->hw->feature_type & AV_FILMSCANNER) {
4706     dev->scanner_type = AV_FILM;
4707     dev->sane.type = "film scanner";
4708   }
4709   else if ( BIT(result[62],6) || BIT(result[62],4) ) {
4710     dev->scanner_type = AV_SHEETFEED;
4711     dev->sane.type =  "sheetfed scanner";
4712   }
4713   else {
4714     dev->scanner_type = AV_FLATBED;
4715     dev->sane.type = "flatbed scanner";
4716   }
4717 
4718   dev->inquiry_new_protocol = BIT (result[39],2);
4719   dev->inquiry_asic_type = (int) result[91];
4720 
4721   dev->inquiry_nvram_read = BIT(result[52],0);
4722   dev->inquiry_power_save_time = BIT(result[52],1);
4723 
4724   dev->inquiry_adf_capability = BIT (result[62], 5);
4725   dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5);
4726   dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4);
4727   /* the first avision scanners (AV3200) do not set the interlaced bit */
4728   if (dev->inquiry_duplex && dev->inquiry_asic_type < AV_ASIC_C6)
4729     dev->inquiry_duplex_interlaced = 1;
4730 
4731   dev->inquiry_paper_length = BIT (result[95], 5);
4732   dev->inquiry_batch_scan = BIT (result[95], 0); /* AV122, DM152 */
4733 
4734   dev->inquiry_detect_accessories = BIT (result[93], 7);
4735 
4736   dev->inquiry_needs_calibration = BIT (result[50], 4);
4737 
4738   dev->inquiry_keeps_window = BIT (result[50], 1);
4739   if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_WINDOW)
4740     dev->inquiry_keeps_window = 0;
4741   if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_WINDOW)
4742     dev->inquiry_keeps_window = 1;
4743 
4744   dev->inquiry_needs_gamma = BIT (result[50], 3);
4745   dev->inquiry_keeps_gamma = BIT (result[50], 2);
4746   if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_GAMMA)
4747     dev->inquiry_keeps_gamma = 0;
4748   if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_GAMMA)
4749     dev->inquiry_keeps_gamma = 1;
4750 
4751   dev->inquiry_3x3_matrix = BIT (result[51], 1);
4752   dev->inquiry_needs_software_colorpack = BIT (result[50],5);
4753 
4754   dev->inquiry_needs_line_pack = BIT (result[94], 6);
4755 
4756   dev->inquiry_adf_need_mirror = BIT (result[51], 0);
4757   dev->inquiry_adf_bgr_order = BIT (result[93], 6);
4758   if (Avision_Device_List [model_num].feature_type & AV_ADF_BGR_ORDER_INVERT)
4759     dev->inquiry_adf_bgr_order = ! dev->inquiry_adf_bgr_order;
4760 
4761   dev->inquiry_light_detect = BIT (result[93], 2);
4762   dev->inquiry_light_control = BIT (result[50], 7);
4763   dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2);
4764 
4765   dev->inquiry_exposure_control = BIT(result[51],7);
4766   if (dev->scanner_type != AV_FILM && !(dev->hw->feature_type & AV_FORCE_FILM))
4767     dev->inquiry_exposure_control = 0;
4768   dev->inquiry_max_shading_target = get_double ( &(result[75]) );
4769 
4770   dev->inquiry_color_boundary = result[54];
4771   if (dev->inquiry_color_boundary == 0)
4772     dev->inquiry_color_boundary = 8;
4773 
4774   dev->inquiry_gray_boundary = result[55];
4775   if (dev->inquiry_gray_boundary == 0)
4776     dev->inquiry_gray_boundary = 8;
4777 
4778   dev->inquiry_dithered_boundary = result[59];
4779   if (dev->inquiry_dithered_boundary == 0)
4780     dev->inquiry_dithered_boundary = 8;
4781 
4782   dev->inquiry_thresholded_boundary = result[57];
4783   if (dev->inquiry_thresholded_boundary == 0)
4784     dev->inquiry_thresholded_boundary = 8;
4785 
4786   dev->inquiry_line_difference = result[53];
4787   /* compensation according to real world hardware */
4788   switch (dev->inquiry_asic_type)
4789   {
4790     case AV_ASIC_C2: /* HP 5300 */
4791     case AV_ASIC_C5: /* HP 53xx R2 */
4792       dev->inquiry_line_difference /= 2; /* HP 5300 */
4793       break;
4794     case AV_ASIC_C7:
4795       dev->inquiry_line_difference *= 2; /* AV610C2 */
4796       break;
4797     default:
4798       ;
4799   }
4800 
4801   if (dev->inquiry_new_protocol) {
4802     dev->inquiry_optical_res = get_double ( &(result[89]) );
4803     dev->inquiry_max_res = get_double ( &(result[44]) );
4804   }
4805   else {
4806     dev->inquiry_optical_res = result[37] * 100;
4807     dev->inquiry_max_res = result[38] * 100;
4808   }
4809 
4810   /* fixup max res */
4811   if (dev->inquiry_optical_res > dev->inquiry_max_res) {
4812     DBG (1, "Inquiry optical resolution > max_resolution, adjusting!\n");
4813     dev->inquiry_max_res = dev->inquiry_optical_res;
4814   }
4815 
4816   if (dev->inquiry_optical_res == 0)
4817     {
4818       DBG (1, "Inquiry optical resolution is invalid!\n");
4819       if (dev->hw->feature_type & AV_FORCE_FILM)
4820 	dev->inquiry_optical_res = 2438; /* verify */
4821       if (dev->scanner_type == AV_SHEETFEED)
4822 	dev->inquiry_optical_res = 300;
4823       else
4824 	dev->inquiry_optical_res = 600;
4825     }
4826   if (dev->inquiry_max_res == 0) {
4827     DBG (1, "Inquiry max resolution is invalid, using 1200 dpi!\n");
4828     dev->inquiry_max_res = 1200;
4829   }
4830 
4831   DBG (1, "attach: optical resolution set to: %d dpi\n", dev->inquiry_optical_res);
4832   DBG (1, "attach: max resolution set to: %d dpi\n", dev->inquiry_max_res);
4833 
4834   if (BIT(result[60],6))
4835     dev->inquiry_channels_per_pixel = 3;
4836   else if (BIT(result[60],7))
4837     dev->inquiry_channels_per_pixel = 1;
4838   else if ( ((result[36] >> 4) & 0x7) > 0)
4839     dev->inquiry_channels_per_pixel = 3;
4840   else
4841     dev->inquiry_channels_per_pixel = 1;
4842 
4843   if (BIT(result[61],1))
4844     dev->inquiry_bits_per_channel = 16;
4845   else if (BIT(result[61],2))
4846     dev->inquiry_bits_per_channel = 12;
4847   else if (BIT(result[61],3))
4848     dev->inquiry_bits_per_channel = 10;
4849   else if (BIT(result[61],4))
4850     dev->inquiry_bits_per_channel = 8;
4851   else if (BIT(result[61],5))
4852     dev->inquiry_bits_per_channel = 6;
4853   else if (BIT(result[61],6))
4854     dev->inquiry_bits_per_channel = 4;
4855   else if (BIT(result[61],7))
4856     dev->inquiry_bits_per_channel = 1;
4857   else
4858     dev->inquiry_bits_per_channel = 8; /* default for old scanners */
4859 
4860   if (dev->hw->feature_type & AV_12_BIT_MODE)
4861     dev->inquiry_bits_per_channel = 12;
4862 
4863   if (! (dev->hw->feature_type & AV_GRAY_MODES))
4864     dev->inquiry_no_gray_modes = BIT(result[93],5);
4865 
4866   DBG (1, "attach: max channels per pixel: %d, max bits per channel: %d\n",
4867     dev->inquiry_channels_per_pixel, dev->inquiry_bits_per_channel);
4868 
4869   if (! (dev->hw->feature_type & AV_NO_BUTTON))
4870     dev->inquiry_buttons = result[92];
4871 
4872   /* get max x/y ranges for the different modes */
4873   {
4874     double base_dpi; /* TODO: make int */
4875     if (dev->scanner_type != AV_FILM) {
4876       base_dpi = AVISION_BASE_RES;
4877     } else {
4878       /* ZP: The right number is 2820, whether it is 40-41, 42-43, 44-45,
4879        * 46-47 or 89-90 I don't know but I would bet for the last !
4880        * ReneR: OK. We use it via the optical_res which we need anyway ...
4881        */
4882       base_dpi = dev->inquiry_optical_res;
4883     }
4884 
4885     /* .1 to slightly increase the size to match the one of American standard paper
4886        formats that would otherwise be .1 mm too large to scan ... */
4887     dev->inquiry_x_ranges [AV_NORMAL_DIM] =
4888       (double)get_double (&(result[81])) * MM_PER_INCH / base_dpi + .1;
4889     dev->inquiry_y_ranges [AV_NORMAL_DIM] =
4890       (double)get_double (&(result[83])) * MM_PER_INCH / base_dpi;
4891 
4892     dev->inquiry_x_ranges [AV_TRANSPARENT_DIM] =
4893       (double)get_double (&(result[77])) * MM_PER_INCH / base_dpi + .1;
4894     dev->inquiry_y_ranges [AV_TRANSPARENT_DIM] =
4895       (double)get_double (&(result[79])) * MM_PER_INCH / base_dpi;
4896 
4897     dev->inquiry_x_ranges [AV_ADF_DIM] =
4898       (double)get_double (&(result[85])) * MM_PER_INCH / base_dpi + .1;
4899     dev->inquiry_y_ranges [AV_ADF_DIM] =
4900       (double)get_double (&(result[87])) * MM_PER_INCH / base_dpi;
4901   }
4902 
4903   dev->inquiry_tune_scan_length = BIT(result[94],2);
4904   if (Avision_Device_List [model_num].feature_type & AV_NO_TUNE_SCAN_LENGTH)
4905     dev->inquiry_tune_scan_length = 0;
4906 
4907   dev->inquiry_background_raster = BIT(result[95],2);
4908 
4909   if (dev->hw->feature_type & AV_NO_BACKGROUND)
4910     dev->inquiry_background_raster = 0;
4911 
4912   if (dev->inquiry_background_raster) {
4913     dev->inquiry_background_raster_pixel =
4914       get_double(&(result[85])) * dev->inquiry_optical_res / AVISION_BASE_RES;
4915   }
4916 
4917   /* check if x/y ranges are valid :-((( */
4918   {
4919     source_mode_dim mode;
4920 
4921     for (mode = AV_NORMAL_DIM; mode < AV_SOURCE_MODE_DIM_LAST; ++ mode)
4922       {
4923 	if (dev->inquiry_x_ranges [mode] != 0 &&
4924 	    dev->inquiry_y_ranges [mode] != 0)
4925 	  {
4926 	    DBG (3, "attach: x/y-range for mode %d is valid!\n", mode);
4927 	    if (force_a4) {
4928 	      DBG (1, "attach: \"force_a4\" found! Using default (ISO A4).\n");
4929 	      dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH;
4930 	      dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH;
4931 	    } else if (force_a3) {
4932 	      DBG (1, "attach: \"force_a3\" found! Using default (ISO A3).\n");
4933 	      dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH;
4934 	      dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH;
4935 	    }
4936 	  }
4937 	else /* mode is invalid */
4938 	  {
4939 	    DBG (1, "attach: x/y-range for mode %d is invalid! Using a default.\n", mode);
4940 	    if (dev->hw->feature_type & AV_FORCE_A3) {
4941 	      dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH;
4942 	      dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH;
4943 	    }
4944 	    else if (dev->hw->feature_type & AV_FORCE_FILM) {
4945 	      dev->inquiry_x_ranges [mode] = FILM_X_RANGE * MM_PER_INCH;
4946 	      dev->inquiry_y_ranges [mode] = FILM_Y_RANGE * MM_PER_INCH;
4947 	    }
4948 	    else {
4949 	      dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH;
4950 
4951 	      if (dev->scanner_type == AV_SHEETFEED)
4952 		dev->inquiry_y_ranges [mode] = SHEETFEED_Y_RANGE * MM_PER_INCH;
4953 	      else
4954 		dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH;
4955 	    }
4956 	  }
4957 	DBG (1, "attach: Mode %d range is now: %f x %f mm.\n",
4958 	     mode,
4959 	     dev->inquiry_x_ranges [mode], dev->inquiry_y_ranges [mode]);
4960       } /* end for all modes */
4961   }
4962 
4963   /* We need a bigger buffer for USB devices, since they seem to have
4964      a firmware bug and do not support reading the calibration data in
4965      tiny chunks */
4966   if (av_con.connection_type == AV_USB)
4967     dev->scsi_buffer_size = 1024 * 1024; /* or 0x10000, used by AV Windows driver during background raster read, ... ? */
4968   else
4969     dev->scsi_buffer_size = sanei_scsi_max_request_size;
4970 
4971   if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980)
4972     dev->read_stripe_size = 16;
4973   else if (dev->inquiry_asic_type >= AV_ASIC_C5)
4974     dev->read_stripe_size = 32;
4975   else  /* tested on AV3200 with it's max of 300dpi @color */
4976     dev->read_stripe_size = 8; /* maybe made dynamic on scan res ... */
4977 
4978   /* normally the data_dq is 0x0a0d - but some newer scanner hang with it ... */
4979   if (dev->inquiry_new_protocol) /* TODO: match on ASIC? which model hung? */
4980     dev->data_dq = 0x0a0d;
4981   else
4982     dev->data_dq = 0;
4983 
4984   avision_close (&av_con);
4985 
4986   ++ num_devices;
4987   dev->next = first_dev;
4988   first_dev = dev;
4989   if (devp)
4990     *devp = dev;
4991 
4992   return SANE_STATUS_GOOD;
4993 
4994  close_scanner_and_return:
4995   avision_close (&av_con);
4996 
4997   return status;
4998 }
4999 
5000 
5001 static SANE_Status
get_tune_scan_length(Avision_Scanner * s)5002 get_tune_scan_length (Avision_Scanner* s)
5003 {
5004   SANE_Status status;
5005   int i;
5006 
5007   struct command_read rcmd;
5008   size_t size;
5009 
5010   struct max_value {
5011     uint8_t max [2];
5012   } payload;
5013 
5014   /* turn on the light */
5015   DBG (3, "get_tune_scan_length:\n");
5016 
5017   memset (&rcmd, 0, sizeof (rcmd));
5018   size = sizeof (payload);
5019 
5020   rcmd.opc = AVISION_SCSI_READ;
5021   rcmd.datatypecode = AVISION_DATATYPECODE_READ_GENERAL_ABILITY_PARAM; /* Read General Ability/Parameter */
5022 
5023   for (i = 1; i <= 8; ++i) {
5024     memset (&payload, 0, sizeof (payload));
5025 
5026     set_double (rcmd.datatypequal, i); /* type */
5027     set_triple (rcmd.transferlen, size);
5028 
5029     status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd),
5030 			  0, 0, &payload, &size);
5031 
5032     if (status != SANE_STATUS_GOOD) {
5033       DBG (1, "get_tune_scan_length: read %d failed (%s)\n", i, sane_strstatus (status));
5034       return status;
5035     }
5036     DBG (1, "get_tune_scan_length: %d: %d\n", i, get_double (payload.max));
5037   }
5038 
5039   return SANE_STATUS_GOOD;
5040 }
5041 
5042 static SANE_Status
send_tune_scan_length(Avision_Scanner * s)5043 send_tune_scan_length (Avision_Scanner* s)
5044 {
5045   Avision_Device* dev = s->hw;
5046 
5047   int top, bottom, dpi;
5048   double offset = 0;
5049 
5050   SANE_Status status;
5051   size_t size;
5052   struct command_send scmd;
5053   struct truncate_attach {
5054     uint8_t vertical [2];
5055  /*   uint8_t horizontal [2]; not send by the Windows driver, yet */
5056   } payload;
5057 
5058   DBG (3, "send_tune_scan_length:\n");
5059 
5060   memset (&scmd, 0, sizeof (scmd));
5061 
5062   size = sizeof (payload);
5063   scmd.opc = AVISION_SCSI_SEND;
5064   scmd.datatypecode = AVISION_DATATYPECODE_ATTACH_TRUNCATE_HEAD; /* Attach/Truncate head(left) of scan length */
5065   set_triple (scmd.transferlen, size);
5066 
5067   /* the SPEC says optical DPI, but real world measuring suggests it is 1200
5068      as in the window descriptor.
5069      MN: This is not true for at least Kodak i1120 where it is optical DPI
5070   */
5071   dpi = 1200;
5072   if (dev->hw->feature_type & AV_OVERSCAN_OPTDPI)
5073     dpi = dev->inquiry_optical_res;
5074 
5075   top = (int) (dpi * SANE_UNFIX (s->val[OPT_OVERSCAN_TOP].w) / MM_PER_INCH);
5076   DBG (3, "send_tune_scan_length: top: %d\n", top);
5077 
5078   /* top offset compensation */
5079   if (dev->adf_offset_compensation) {
5080     if (s->avdimen.interlaced_duplex)
5081       offset += fmax(0, fmax(dev->hw->offset.duplex.front.top,
5082                              dev->hw->offset.duplex.rear.top) );
5083     else if (s->source_mode == AV_ADF)
5084       offset += fmax(0, dev->hw->offset.front.top);
5085 
5086     /* first page offset */
5087     if (dev->hw->offset.first > 0)
5088       offset += dev->hw->offset.first;
5089 
5090     /* convert to lines */
5091     int top_offset = (int) (dpi * offset / MM_PER_INCH);
5092     top += top_offset;
5093     DBG (3, "send_tune_scan_length: top offset: %d\n", top_offset);
5094   }
5095 
5096   set_double (scmd.datatypequal, 0x0001); /* attach, 0x000 is shorten */
5097   set_double (payload.vertical, top);
5098   /* set_double (payload.horizontal, 0); */
5099 
5100   /* we always send it, even for 0 as the scanner keeps it in RAM and
5101      previous runs could already have set something */
5102 
5103   status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5104 			&payload, sizeof (payload), 0, 0);
5105 
5106   if (status != SANE_STATUS_GOOD) {
5107     DBG (1, "send_tune_scan_length: send top/left failed (%s)\n", sane_strstatus (status));
5108     return status;
5109   }
5110 
5111   scmd.datatypecode = AVISION_DATATYPECODE_ATTACH_TRUNCATE_TAIL; /* Attach/Truncate tail(right) of scan length */
5112   bottom = (int) (dpi * SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w) / MM_PER_INCH);
5113   DBG (3, "send_tune_scan_length: bottom: %d\n", bottom);
5114 
5115   /* bottom offset compensation */
5116   offset = 0;
5117   if (dev->adf_offset_compensation) {
5118     if (s->avdimen.interlaced_duplex)
5119       offset += fmax(0, fmax(dev->hw->offset.duplex.front.bottom,
5120                              dev->hw->offset.duplex.rear.bottom) );
5121     else if (s->source_mode == AV_ADF)
5122       offset += fmax(0, dev->hw->offset.front.bottom);
5123 
5124     /* first page offset */
5125     if (dev->hw->offset.first < 0)
5126       offset += fabs(dev->hw->offset.first);
5127 
5128     /* convert to lines */
5129     int bottom_offset = (int) (dpi * offset / MM_PER_INCH);
5130     bottom += bottom_offset;
5131     DBG (3, "send_tune_scan_length: bottom offset: %d\n", bottom_offset);
5132   }
5133 
5134   set_double (payload.vertical, bottom);
5135   /*set_double (payload.horizontal, 0); */
5136 
5137   size = sizeof (payload);
5138   status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5139 			&payload, sizeof (payload), 0, 0);
5140 
5141   if (status != SANE_STATUS_GOOD) {
5142     DBG (1, "send_tune_scan_length: send bottom/right failed (%s)\n", sane_strstatus (status));
5143     return status;
5144   }
5145 
5146   return SANE_STATUS_GOOD;
5147 }
5148 
5149 static SANE_Status
additional_probe(Avision_Scanner * s)5150 additional_probe (Avision_Scanner* s)
5151 {
5152   Avision_Device* dev = s->hw;
5153 
5154   /* we should wait until the scanner is ready before we
5155      perform further actions */
5156 
5157   SANE_Status status;
5158   /* try to retrieve additional accessory information */
5159   if (dev->inquiry_detect_accessories) {
5160     status = get_accessories_info (s);
5161     if (status != SANE_STATUS_GOOD)
5162       return status;
5163   }
5164 
5165   /* for a film scanner try to retrieve additional frame information */
5166   if (dev->scanner_type == AV_FILM) {
5167     status = get_frame_info (s);
5168     if (status != SANE_STATUS_GOOD)
5169       return status;
5170   }
5171 
5172   /* no scanner did support this so far: tried on AV220, DM152 */
5173   if (0 && dev->inquiry_duplex) {
5174     status = get_duplex_info (s);
5175     if (status != SANE_STATUS_GOOD)
5176       return status;
5177   }
5178 
5179   /* get overscan ("head/tail tune") information: hangs AV220, zeros on AV122 */
5180   if (0 && dev->inquiry_tune_scan_length) {
5181     status = get_tune_scan_length (s);
5182     if (status != SANE_STATUS_GOOD)
5183       return status;
5184   }
5185 
5186   /* create dynamic *-mode entries */
5187   if (!dev->inquiry_no_gray_modes)
5188   {
5189     if (dev->inquiry_bits_per_channel > 0) {
5190       add_color_mode (dev, AV_THRESHOLDED, SANE_VALUE_SCAN_MODE_LINEART);
5191       add_color_mode (dev, AV_DITHERED, "Dithered");
5192     }
5193 
5194     if (dev->inquiry_bits_per_channel >= 8)
5195       add_color_mode (dev, AV_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY);
5196 
5197     if (dev->inquiry_bits_per_channel == 12)
5198       add_color_mode (dev, AV_GRAYSCALE12, "12bit Gray");
5199 
5200     if (dev->inquiry_bits_per_channel >= 16)
5201       add_color_mode (dev, AV_GRAYSCALE16, "16bit Gray");
5202   }
5203 
5204   if (dev->inquiry_channels_per_pixel > 1) {
5205     add_color_mode (dev, AV_TRUECOLOR, SANE_VALUE_SCAN_MODE_COLOR);
5206 
5207     if (dev->inquiry_bits_per_channel == 12)
5208       add_color_mode (dev, AV_TRUECOLOR12, "12bit Color");
5209 
5210     if (dev->inquiry_bits_per_channel >= 16)
5211       add_color_mode (dev, AV_TRUECOLOR16, "16bit Color");
5212   }
5213 
5214   /* now choose the default mode - avoiding the 12/16 bit modes */
5215   dev->color_list_default = last_color_mode (dev);
5216   if (dev->inquiry_bits_per_channel > 8 && dev->color_list_default > 0) {
5217     dev->color_list_default--;
5218   }
5219 
5220   if (dev->scanner_type == AV_SHEETFEED)
5221     {
5222       add_source_mode (dev, AV_ADF, "ADF Front");
5223     }
5224   else
5225     {
5226       add_source_mode (dev, AV_NORMAL, "Normal");
5227 
5228       if (dev->inquiry_light_box_present)
5229 	add_source_mode (dev, AV_TRANSPARENT, "Transparency");
5230 
5231       if (dev->inquiry_adf_present)
5232         add_source_mode (dev, AV_ADF, "ADF Front");
5233     }
5234 
5235   if (dev->inquiry_duplex) {
5236     if (dev->inquiry_duplex_interlaced && !(dev->hw->feature_type & AV_NO_REAR))
5237       add_source_mode (dev, AV_ADF_REAR, "ADF Back");
5238     add_source_mode (dev, AV_ADF_DUPLEX, "ADF Duplex");
5239   }
5240 
5241   return SANE_STATUS_GOOD;
5242 }
5243 
5244 static SANE_Status
get_calib_format(Avision_Scanner * s,struct calibration_format * format)5245 get_calib_format (Avision_Scanner* s, struct calibration_format* format)
5246 {
5247   SANE_Status status;
5248 
5249   struct command_read rcmd;
5250   uint8_t result [32];
5251   size_t size;
5252 
5253   DBG (3, "get_calib_format:\n");
5254 
5255   size = sizeof (result);
5256 
5257   memset (&rcmd, 0, sizeof (rcmd));
5258   rcmd.opc = AVISION_SCSI_READ;
5259   rcmd.datatypecode = AVISION_DATATYPECODE_GET_CALIBRATION_FORMAT; /* get calibration format */
5260   set_double (rcmd.datatypequal, s->hw->data_dq);
5261   set_triple (rcmd.transferlen, size);
5262 
5263   DBG (3, "get_calib_format: read_data: %lu bytes\n", (u_long) size);
5264   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
5265   if (status != SANE_STATUS_GOOD || size != sizeof (result) ) {
5266     status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
5267     DBG (1, "get_calib_format: read calib. info failed (%s)\n", sane_strstatus (status) );
5268     return status;
5269   }
5270 
5271   debug_print_calib_format (3, "get_calib_format", result);
5272 
5273   format->pixel_per_line = (uint16_t) get_double (&(result[0]));
5274   format->bytes_per_channel = result[2];
5275   format->lines = result[3];
5276   format->flags = result[4];
5277   format->ability1 = result[5];
5278   format->r_gain = result[6];
5279   format->g_gain = result[7];
5280   format->b_gain = result[8];
5281   format->r_shading_target = (uint16_t) get_double (&(result[9]));
5282   format->g_shading_target = (uint16_t) get_double (&(result[11]));
5283   format->b_shading_target = (uint16_t) get_double (&(result[13]));
5284   format->r_dark_shading_target = (uint16_t) get_double (&(result[15]));
5285   format->g_dark_shading_target = (uint16_t) get_double (&(result[17]));
5286   format->b_dark_shading_target = (uint16_t) get_double (&(result[19]));
5287 
5288   /* now translate to normal! */
5289   /* firmware return R--RG--GB--B with 3 line count */
5290   /* software format it as 1 line if true color scan */
5291   /* only line interleave format to be supported */
5292 
5293   if (color_mode_is_color (s->c_mode) || BIT(format->ability1, 3)) {
5294     format->channels = 3;
5295     format->lines /= 3; /* line interleave */
5296   }
5297   else
5298     format->channels = 1;
5299 
5300   DBG (3, "get_calib_format: channels: %d\n", format->channels);
5301 
5302   return SANE_STATUS_GOOD;
5303 }
5304 
5305 static SANE_Status
get_calib_data(Avision_Scanner * s,uint8_t data_type,uint8_t * calib_data,size_t calib_size)5306 get_calib_data (Avision_Scanner* s, uint8_t data_type,
5307 		uint8_t* calib_data,
5308 		size_t calib_size)
5309 {
5310   SANE_Status status;
5311   uint8_t *calib_ptr;
5312 
5313   size_t get_size, data_size, chunk_size;
5314 
5315   struct command_read rcmd;
5316 
5317   chunk_size = calib_size;
5318 
5319   DBG (3, "get_calib_data: type %x, size %lu, chunk_size: %lu\n",
5320        data_type, (u_long) calib_size, (u_long) chunk_size);
5321 
5322   memset (&rcmd, 0, sizeof (rcmd));
5323 
5324   rcmd.opc = AVISION_SCSI_READ;
5325   rcmd.datatypecode = data_type;
5326   set_double (rcmd.datatypequal, s->hw->data_dq);
5327 
5328   calib_ptr = calib_data;
5329   get_size = chunk_size;
5330   data_size = calib_size;
5331 
5332   while (data_size) {
5333     if (get_size > data_size)
5334       get_size = data_size;
5335 
5336     read_constrains(s, get_size);
5337 
5338     set_triple (rcmd.transferlen, get_size);
5339 
5340     DBG (3, "get_calib_data: Reading %ld bytes calibration data\n",
5341          (long)get_size);
5342 
5343     status = avision_cmd (&s->av_con, &rcmd,
5344 			  sizeof (rcmd), 0, 0, calib_ptr, &get_size);
5345     if (status != SANE_STATUS_GOOD) {
5346       DBG (1, "get_calib_data: read data failed (%s)\n",
5347 	   sane_strstatus (status));
5348       return status;
5349     }
5350 
5351     DBG (3, "get_calib_data: Got %ld bytes calibration data\n", (long)get_size);
5352 
5353     data_size -= get_size;
5354     calib_ptr += get_size;
5355   }
5356 
5357   return SANE_STATUS_GOOD;
5358 }
5359 
5360 static SANE_Status
set_calib_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * dark_data,uint8_t * white_data)5361 set_calib_data (Avision_Scanner* s, struct calibration_format* format,
5362 		uint8_t* dark_data, uint8_t* white_data)
5363 {
5364   Avision_Device* dev = s->hw;
5365 
5366   const size_t elements_per_line = format->pixel_per_line * format->channels;
5367 
5368   SANE_Status status;
5369 
5370   uint8_t send_type;
5371   uint16_t send_type_q;
5372 
5373   struct command_send scmd;
5374 
5375   size_t i;
5376 
5377   DBG (3, "set_calib_data:\n");
5378 
5379   send_type = 0x82; /* download calibration data */
5380 
5381   /* do we use a color mode? */
5382   if (format->channels > 1) {
5383     send_type_q = 0x12; /* color calib data */
5384   }
5385   else {
5386     if (dev->hw->feature_type & AV_GRAY_CALIB_BLUE)
5387       send_type_q = 0x2; /* gray/bw calib data on the blue channel (AV610) */
5388     else
5389       send_type_q = 0x11; /* gray/bw calib data */
5390   }
5391 
5392   memset (&scmd, 0x00, sizeof (scmd));
5393   scmd.opc = AVISION_SCSI_SEND;
5394   scmd.datatypecode = send_type;
5395 
5396   /* data corrections due to dark calibration data merge */
5397   if (BIT (format->ability1, 2) ) {
5398     DBG (3, "set_calib_data: merging dark calibration data\n");
5399     for (i = 0; i < elements_per_line; ++i) {
5400       uint16_t value_orig = (uint16_t) get_double_le (white_data + i*2);
5401       uint16_t value_new = value_orig;
5402 
5403       value_new &= 0xffc0;
5404       value_new |= (uint16_t) ((get_double_le (dark_data + i*2) >> 10) & 0x3f);
5405 
5406       DBG (9, "set_calib_data: element %zu, dark difference %d\n",
5407 	   i, value_orig - value_new);
5408 
5409       set_double_le ((white_data + i*2), value_new);
5410     }
5411   }
5412 
5413   /* send data in one command? */
5414   /* FR: HP5370 reports one-pass, but needs multi (or other format in single) */
5415   if (format->channels == 1 ||
5416       ( ( (dev->hw->feature_type & AV_ONE_CALIB_CMD) ||
5417 	  ! BIT(format->ability1, 0) ) &&
5418 	! (dev->hw->feature_type & AV_MULTI_CALIB_CMD) ) )
5419     /* one command (most scanners) */
5420     {
5421       size_t send_size = elements_per_line * 2;
5422       DBG (3, "set_calib_data: all channels in one command\n");
5423       DBG (3, "set_calib_data: send_size: %zu\n", send_size);
5424 
5425       memset (&scmd, 0, sizeof (scmd) );
5426       scmd.opc = AVISION_SCSI_SEND;
5427       scmd.datatypecode = send_type;
5428       set_double (scmd.datatypequal, send_type_q);
5429       set_triple (scmd.transferlen, send_size);
5430 
5431       status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5432 			    (char*) white_data, send_size, 0, 0);
5433       /* not return immediately to free mem at the end */
5434     }
5435   else /* send data channel by channel (some USB ones) */
5436     {
5437       size_t conv_out_size = format->pixel_per_line * 2;
5438       uint16_t* conv_out_data; /* here it is save to use 16bit data
5439 				   since we only move whole words around */
5440 
5441       DBG (3, "set_calib_data: channels in single commands\n");
5442 
5443       conv_out_data =  (uint16_t*) malloc (conv_out_size);
5444       if (!conv_out_data) {
5445 	status = SANE_STATUS_NO_MEM;
5446       }
5447       else {
5448 	int channel;
5449 	for (channel = 0; channel < 3; ++ channel)
5450 	  {
5451 	    int i;
5452 
5453 	    /* no need for endianness handling since whole word copy */
5454 	    uint16_t* casted_avg_data = (uint16_t*) white_data;
5455 
5456 	    DBG (3, "set_calib_data_calibration: channel: %i\n", channel);
5457 
5458 	    for (i = 0; i < format->pixel_per_line; ++ i)
5459 	      conv_out_data [i] = casted_avg_data [i * 3 + channel];
5460 
5461 	    DBG (3, "set_calib_data: sending %zu bytes now\n",
5462 		 conv_out_size);
5463 
5464 	    memset (&scmd, 0, sizeof (scmd));
5465 	    scmd.opc = AVISION_SCSI_SEND;
5466 	    scmd.datatypecode = send_type; /* send calibration data */
5467 	    set_double (scmd.datatypequal, channel);
5468 	    set_triple (scmd.transferlen, conv_out_size);
5469 
5470 	    status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
5471 				  conv_out_data, conv_out_size, 0, 0);
5472 	    if (status != SANE_STATUS_GOOD) {
5473 	      DBG (3, "set_calib_data: send_data failed (%s)\n",
5474 		   sane_strstatus (status));
5475 	      /* not return immediately to free mem at the end */
5476 	    }
5477 	  } /* end for each channel */
5478 	free (conv_out_data);
5479       } /* end else send calib data*/
5480     }
5481 
5482   return SANE_STATUS_GOOD;
5483 }
5484 
5485 /* Sort data pixel by pixel and average first 2/3 of the data.
5486    The caller has to free return pointer. R,G,B pixels
5487    interleave to R,G,B line interleave.
5488 
5489    The input data data is in 16 bits little endian, always.
5490    That is a = b[1] << 8 + b[0] in all system.
5491 
5492    We convert it to SCSI high-endian (big-endian) since we use it all
5493    over the place anyway .... - Sorry for this mess. */
5494 
5495 static uint8_t*
sort_and_average(struct calibration_format * format,uint8_t * data)5496 sort_and_average (struct calibration_format* format, uint8_t* data)
5497 {
5498   const size_t elements_per_line = format->pixel_per_line * format->channels;
5499   const size_t stride = format->bytes_per_channel * elements_per_line;
5500   size_t i, line;
5501 
5502   uint8_t *sort_data, *avg_data;
5503 
5504   DBG (1, "sort_and_average:\n");
5505 
5506   if (!format || !data)
5507     return NULL;
5508 
5509   sort_data = malloc (format->lines * 2);
5510   if (!sort_data)
5511     return NULL;
5512 
5513   avg_data = malloc (elements_per_line * 2);
5514   if (!avg_data) {
5515     free (sort_data);
5516     return NULL;
5517   }
5518 
5519   /* for each pixel */
5520   for (i = 0; i < elements_per_line; ++ i)
5521     {
5522       uint8_t* ptr1 = data + i * format->bytes_per_channel;
5523       uint16_t temp;
5524 
5525       /* copy all lines for pixel i into the linear array sort_data */
5526       for (line = 0; line < format->lines; ++ line) {
5527 	uint8_t* ptr2 = ptr1 + line * stride; /* pixel */
5528 
5529 	if (format->bytes_per_channel == 1)
5530 	  temp = 0xffff * *ptr2 / 255;
5531 	else
5532 	  temp = get_double_le (ptr2);	  /* little-endian! */
5533 	set_double ((sort_data + line*2), temp); /* store big-endian */
5534 	/* DBG (7, "ReneR to sort: %x\n", temp); */
5535       }
5536 
5537       temp = bubble_sort (sort_data, format->lines);
5538       /* DBG (7, "ReneR averaged: %x\n", temp); */
5539       set_double ((avg_data + i*2), temp); /* store big-endian */
5540     }
5541 
5542   free ((void *) sort_data);
5543   return avg_data;
5544 }
5545 
5546 /* shading data is 16bits little endian format when send/read from firmware */
5547 static void
compute_dark_shading_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * data)5548 compute_dark_shading_data (Avision_Scanner* s,
5549 			   struct calibration_format* format, uint8_t* data)
5550 {
5551   uint16_t map_value = DEFAULT_DARK_SHADING;
5552   uint16_t rgb_map_value[3];
5553 
5554   int elements_per_line, i;
5555 
5556   DBG (3, "compute_dark_shading_data:\n");
5557 
5558   if (s->hw->inquiry_max_shading_target != INVALID_DARK_SHADING)
5559     map_value = (uint16_t) (s->hw->inquiry_max_shading_target << 8);
5560 
5561   rgb_map_value[0] = format->r_dark_shading_target;
5562   rgb_map_value[1] = format->g_dark_shading_target;
5563   rgb_map_value[2] = format->b_dark_shading_target;
5564 
5565   for (i = 0; i < format->channels; ++i) {
5566     if (rgb_map_value[i] == INVALID_DARK_SHADING)
5567       rgb_map_value[i] = map_value;
5568   }
5569 
5570   if (format->channels == 1) {
5571     /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */
5572     rgb_map_value[0] = rgb_map_value[1] = rgb_map_value[2] = rgb_map_value[1];
5573   }
5574 
5575   elements_per_line = format->pixel_per_line * format->channels;
5576 
5577   /* Check line interleave or pixel interleave. */
5578   /* It seems no ASIC use line interleave right now. */
5579   /* Avision SCSI protocol document has bad description. */
5580   for (i = 0; i < elements_per_line; ++i)
5581     {
5582       uint16_t tmp_data = (uint16_t) get_double_le((data + i*2));
5583       if (tmp_data > rgb_map_value[i % 3]) {
5584 	set_double ((data + i*2), tmp_data - rgb_map_value[i % 3]);
5585       }
5586       else {
5587 	set_double ((data + i*2), 0);
5588       }
5589     }
5590 }
5591 
5592 static void
compute_white_shading_data(Avision_Scanner * s,struct calibration_format * format,uint8_t * data)5593 compute_white_shading_data (Avision_Scanner* s,
5594 			    struct calibration_format* format, uint8_t* data)
5595 {
5596   int i;
5597   uint16_t inquiry_mst = DEFAULT_WHITE_SHADING;
5598   uint16_t mst[3];
5599 
5600   int elements_per_line = format->pixel_per_line * format->channels;
5601 
5602   /* debug counter */
5603   int values_invalid = 0;
5604   int values_limitted = 0;
5605 
5606   DBG (3, "compute_white_shading_data:\n");
5607 
5608   if (s->hw->inquiry_max_shading_target != INVALID_WHITE_SHADING)
5609     inquiry_mst = (uint16_t) (s->hw->inquiry_max_shading_target << 4);
5610 
5611   mst[0] = format->r_shading_target;
5612   mst[1] = format->g_shading_target;
5613   mst[2] = format->b_shading_target;
5614 
5615   for (i = 0; i < 3; ++i) {
5616     if (mst[i] == INVALID_WHITE_SHADING) /* mst[i] > MAX_WHITE_SHADING) */  {
5617       DBG (3, "compute_white_shading_data: target %d invalid (%x) using inquiry (%x)\n",
5618 	   i, mst[i], inquiry_mst);
5619       mst[i] = inquiry_mst;
5620     }
5621     /* some firmware versions seems to return the bytes swapped? */
5622     else if (mst[i] < 0x110) {
5623       uint8_t* swap_mst = (uint8_t*) &mst[i];
5624       uint8_t low_nibble_mst = swap_mst [0];
5625       swap_mst [0] = swap_mst[1];
5626       swap_mst [1] = low_nibble_mst;
5627 
5628       DBG (3, "compute_white_shading_data: target %d: bytes swapped.\n", i);
5629     }
5630     if (mst[i] < DEFAULT_WHITE_SHADING / 2) {
5631       DBG (3, "compute_white_shading_data: target %d: too low (%d) using default (%d).\n",
5632 	   i, mst[i], DEFAULT_WHITE_SHADING);
5633       mst[i] = DEFAULT_WHITE_SHADING;
5634     }
5635     else
5636       DBG (3, "compute_white_shading_data: target %d: %x\n", i, mst[0]);
5637   }
5638 
5639   /* some Avision example code was present here until SANE/Avision
5640    * BUILD 57. */
5641 
5642   if (format->channels == 1) {
5643     /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */
5644     mst[0] = mst[1] = mst[2] = mst[1];
5645   }
5646 
5647   /* calculate calibration data */
5648   for (i = 0; i < elements_per_line; ++ i)
5649     {
5650       int result;
5651       /* calculate calibration value for pixel i */
5652       uint16_t tmp_data = (uint16_t) get_double((data + i*2));
5653 
5654       if (tmp_data == INVALID_WHITE_SHADING) {
5655        	tmp_data = DEFAULT_WHITE_SHADING;
5656 	++ values_invalid;
5657       }
5658 
5659       result = (int) ( (int)mst[i % 3] * WHITE_MAP_RANGE / (tmp_data + 0.5));
5660 
5661       /* sanity check for over-amplification, clipping */
5662       if (result > MAX_WHITE_SHADING) {
5663 	result = WHITE_MAP_RANGE;
5664 	++ values_limitted;
5665       }
5666 
5667       /* for visual debugging ... */
5668       if (static_calib_list [i % 3] == SANE_TRUE)
5669 	result = 0xA000;
5670 
5671       /* the output to the scanner will be 16 bit little endian again */
5672       set_double_le ((data + i*2), result);
5673     }
5674   DBG (3, "compute_white_shading_data: %d invalid, %d limited\n",
5675        values_invalid, values_limitted);
5676 }
5677 
5678 /* old_r_calibration was here until SANE/Avision BUILD 90 */
5679 
5680 static SANE_Status
normal_calibration(Avision_Scanner * s)5681 normal_calibration (Avision_Scanner* s)
5682 {
5683   SANE_Status status;
5684 
5685   struct calibration_format calib_format;
5686 
5687   size_t calib_data_size;
5688   int calib_bytes_per_line;
5689   uint8_t read_type;
5690   uint8_t *calib_tmp_data;
5691 
5692   DBG (1, "normal_calibration:\n");
5693 
5694   /* get calibration format and data */
5695   status = get_calib_format (s, &calib_format);
5696   if (status != SANE_STATUS_GOOD)
5697     return status;
5698 
5699   /* check if need do calibration */
5700   if (calib_format.flags != 1 && !(s->hw->hw->feature_type & AV_FORCE_CALIB)) {
5701     DBG (1, "normal_calibration: Scanner claims no calibration needed -> skipped!\n");
5702     return SANE_STATUS_GOOD;
5703   }
5704 
5705   /* calculate calibration data size for read from scanner */
5706   /* size = lines * bytes_per_channel * pixels_per_line * channel */
5707   calib_bytes_per_line = calib_format.bytes_per_channel *
5708     calib_format.pixel_per_line * calib_format.channels;
5709 
5710   calib_data_size = (size_t) calib_format.lines * (size_t) calib_bytes_per_line;
5711 
5712   calib_tmp_data = malloc (calib_data_size);
5713   if (!calib_tmp_data)
5714     return SANE_STATUS_NO_MEM;
5715 
5716   /* check if we need to do dark calibration (shading) */
5717   if (BIT(calib_format.ability1, 2))
5718     {
5719       DBG (1, "normal_calibration: reading dark data\n");
5720       /* read dark calib data */
5721       status = get_calib_data (s, 0x66, calib_tmp_data, calib_data_size);
5722 
5723       if (status != SANE_STATUS_GOOD) {
5724 	free (calib_tmp_data);
5725 	return status;
5726       }
5727 
5728       /* process dark data: sort and average. */
5729 
5730       if (s->dark_avg_data) {
5731 	free (s->dark_avg_data);
5732 	s->dark_avg_data = 0;
5733       }
5734       s->dark_avg_data = sort_and_average (&calib_format, calib_tmp_data);
5735       if (!s->dark_avg_data) {
5736 	free (calib_tmp_data);
5737 	return SANE_STATUS_NO_MEM;
5738       }
5739       compute_dark_shading_data (s, &calib_format, s->dark_avg_data);
5740     }
5741 
5742   /* do we use a color mode? */
5743   if (calib_format.channels > 1) {
5744     DBG (3, "normal_calibration: using color calibration\n");
5745     read_type = 0x62; /* read color calib data */
5746   }
5747   else {
5748     DBG (3, "normal_calibration: using gray calibration\n");
5749     read_type = 0x61; /* gray calib data */
5750   }
5751 
5752   /* do white calibration: read gray or color data */
5753   status = get_calib_data (s, read_type, calib_tmp_data, calib_data_size);
5754 
5755   if (status != SANE_STATUS_GOOD) {
5756     free (calib_tmp_data);
5757     return status;
5758   }
5759 
5760   if (0) /* debug */
5761     {
5762       FILE* f = NULL;
5763       f = fopen ("calibration-white.pnm", "w");
5764       write_pnm_header (f, AV_GRAYSCALE, calib_format.bytes_per_channel * 8,
5765 			calib_format.pixel_per_line,
5766 			calib_format.lines * calib_format.channels);
5767 
5768       fwrite (calib_tmp_data, 1, calib_data_size, f);
5769       fclose (f);
5770     }
5771 
5772   if (s->white_avg_data) {
5773     free (s->white_avg_data);
5774     s->white_avg_data = 0;
5775   }
5776   s->white_avg_data = sort_and_average (&calib_format, calib_tmp_data);
5777   if (!s->white_avg_data) {
5778     free (calib_tmp_data);
5779     return SANE_STATUS_NO_MEM;
5780   }
5781 
5782   /* decrease white average data (if dark average data is present) */
5783   if (s->dark_avg_data) {
5784     int elements_per_line = calib_format.pixel_per_line * calib_format.channels;
5785     int i;
5786 
5787     DBG (1, "normal_calibration: dark data present - decreasing white average data\n");
5788 
5789     for (i = 0; i < elements_per_line; ++ i) {
5790       s->white_avg_data[i] -= s->dark_avg_data[i];
5791     }
5792   }
5793 
5794   compute_white_shading_data (s, &calib_format, s->white_avg_data);
5795 
5796   status = set_calib_data (s, &calib_format,
5797 			   s->dark_avg_data, s->white_avg_data);
5798 
5799   free (calib_tmp_data);
5800   return status;
5801 }
5802 
5803 /* next was taken from the GIMP and is a bit modified ... ;-)
5804  * original Copyright (C) 1995 Spencer Kimball and Peter Mattis
5805  */
5806 static double
brightness_contrast_func(double brightness,double contrast,double value)5807 brightness_contrast_func (double brightness, double contrast, double value)
5808 {
5809   double nvalue;
5810   double power;
5811 
5812   /* apply brightness */
5813   if (brightness < 0.0)
5814     value = value * (1.0 + brightness);
5815   else
5816     value = value + ((1.0 - value) * brightness);
5817 
5818   /* apply contrast */
5819   if (contrast < 0.0)
5820     {
5821       if (value > 0.5)
5822 	nvalue = 1.0 - value;
5823       else
5824 	nvalue = value;
5825       if (nvalue < 0.0)
5826 	nvalue = 0.0;
5827       nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + contrast));
5828       if (value > 0.5)
5829 	value = 1.0 - nvalue;
5830       else
5831 	value = nvalue;
5832     }
5833   else
5834     {
5835       if (value > 0.5)
5836 	nvalue = 1.0 - value;
5837       else
5838 	nvalue = value;
5839       if (nvalue < 0.0)
5840 	nvalue = 0.0;
5841       power = (contrast == 1.0) ? 127 : 1.0 / (1.0 - contrast);
5842       nvalue = 0.5 * pow (2.0 * nvalue, power);
5843       if (value > 0.5)
5844 	value = 1.0 - nvalue;
5845       else
5846 	value = nvalue;
5847     }
5848   return value;
5849 }
5850 
5851 static SANE_Status
send_gamma(Avision_Scanner * s)5852 send_gamma (Avision_Scanner* s)
5853 {
5854   Avision_Device* dev = s->hw;
5855   SANE_Status status = SANE_STATUS_GOOD;
5856 
5857   int invert_table = 0;
5858 
5859   size_t gamma_table_raw_size;
5860   size_t gamma_table_size;
5861   size_t gamma_values;
5862 
5863   struct command_send scmd;
5864   uint8_t *gamma_data;
5865 
5866   int color; /* current color */
5867   size_t i; /* big table index */
5868   size_t j; /* little table index */
5869   size_t k; /* big table sub index */
5870   double v1, v2;
5871 
5872   double brightness;
5873   double contrast;
5874 
5875   if (dev->inquiry_asic_type != AV_ASIC_OA980)
5876     invert_table = (s->c_mode == AV_THRESHOLDED) || (s->c_mode == AV_DITHERED);
5877 
5878   switch (dev->inquiry_asic_type)
5879     {
5880     case AV_ASIC_Cx:
5881     case AV_ASIC_C1:
5882       gamma_table_raw_size = 4096;
5883       gamma_table_size = 2048;
5884       break;
5885     case AV_ASIC_C5:
5886       gamma_table_raw_size = 256;
5887       gamma_table_size = 256;
5888       break;
5889       break;
5890     case AV_ASIC_OA980:
5891       gamma_table_raw_size = 4096;
5892       gamma_table_size = 4096;
5893       break;
5894     case AV_ASIC_OA982:
5895       gamma_table_raw_size = 256;
5896       gamma_table_size = 256;
5897       break;
5898     default:
5899       gamma_table_raw_size = 512; /* SPEC claims: 256 ... ? */
5900       gamma_table_size = 512;
5901     }
5902 
5903   gamma_values = gamma_table_size / 256;
5904 
5905   DBG (3, "send_gamma: table_raw_size: %lu, table_size: %lu\n",
5906        (u_long) gamma_table_raw_size, (u_long) gamma_table_size);
5907   DBG (3, "send_gamma: values: %lu, invert_table: %d\n",
5908        (u_long) gamma_values, invert_table);
5909 
5910   /* prepare for emulating contrast, brightness ... via the gamma-table */
5911   brightness = SANE_UNFIX (s->val[OPT_BRIGHTNESS].w);
5912   brightness /= 100;
5913   contrast = SANE_UNFIX (s->val[OPT_CONTRAST].w);
5914   contrast /= 100;
5915 
5916   DBG (3, "send_gamma: brightness: %f, contrast: %f\n", brightness, contrast);
5917 
5918   gamma_data = malloc (gamma_table_raw_size);
5919   if (!gamma_data)
5920     return SANE_STATUS_NO_MEM;
5921 
5922   memset (&scmd, 0, sizeof (scmd) );
5923 
5924   scmd.opc = AVISION_SCSI_SEND;
5925   scmd.datatypecode = AVISION_DATATYPECODE_DOWNLOAD_GAMMA_TABLE; /* 0x81 for download gamma table */
5926   set_triple (scmd.transferlen, gamma_table_raw_size);
5927 
5928   for (color = 0; color < 3 && status == SANE_STATUS_GOOD; ++ color)
5929     {
5930       /* color: 0=red; 1=green; 2=blue */
5931       set_double (scmd.datatypequal, color);
5932 
5933       i = 0; /* big table index */
5934       for (j = 0; j < 256; ++ j) /* little table index */
5935 	{
5936 	  /* calculate mode dependent values v1 and v2
5937 	   * v1 <- current value for table
5938 	   * v2 <- next value for table (for interpolation)
5939 	   */
5940 	  switch (s->c_mode)
5941 	    {
5942 	    case AV_TRUECOLOR:
5943 	    case AV_TRUECOLOR12:
5944 	    case AV_TRUECOLOR16:
5945 	      {
5946 		v1 = (double) s->gamma_table [1 + color][j];
5947 		if (j == 255)
5948 		  v2 = (double) v1;
5949 		else
5950 		  v2 = (double) s->gamma_table [1 + color][j + 1];
5951 	      }
5952 	      break;
5953 	    default:
5954 	      /* for all other modes: */
5955 	      {
5956 		v1 = (double) s->gamma_table [0][j];
5957 		if (j == 255)
5958 		  v2 = (double) v1;
5959 		else
5960 		  v2 = (double) s->gamma_table [0][j + 1];
5961 	      }
5962 	    } /*end switch */
5963 
5964 	  /* Emulate brightness and contrast (at least the Avision AV6[2,3]0
5965 	   * as well as many others do not have a hardware implementation,
5966 	   * --$. The function was taken from the GIMP source - maybe I'll
5967 	   * optimize it in the future (when I have spare time). */
5968 
5969 	  v1 /= 255;
5970 	  v2 /= 255;
5971 
5972 	  v1 = (brightness_contrast_func (brightness, contrast, v1) );
5973 	  v2 = (brightness_contrast_func (brightness, contrast, v2) );
5974 
5975 	  v1 *= 255;
5976 	  v2 *= 255;
5977 
5978 	  if (invert_table) {
5979 	    v1 = 255 - v1;
5980 	    v2 = 255 - v2;
5981 	    if (v1 <= 0)
5982 	      v1 = 0;
5983 	    if (v2 <= 0)
5984 	      v2 = 0;
5985 	  }
5986 
5987           if (s->hw->hw->feature_type & AV_GAMMA_UINT16) {
5988             /* Use some pointer-cast magic to use gamma_data as uint16 array
5989                and write as big-endian since values get swapped */
5990             ((uint16_t *)gamma_data) [i++] = (uint16_t)v1<<8;
5991           } else {
5992             /* interpolate gamma_values to gamma_data */
5993 	    for (k = 0; k < gamma_values; ++ k, ++ i) {
5994 	      gamma_data [i] = (uint8_t)
5995 	        (((v1 * (double) (gamma_values - k)) + (v2 * (double) k) ) / (double) gamma_values);
5996 	    }
5997           }
5998 
5999 	}
6000 
6001       /* with AV_GAMMA_UINT16 only every second value is filled, so double i */
6002       if (s->hw->hw->feature_type & AV_GAMMA_UINT16)
6003         i *= 2;
6004 
6005       /* fill the gamma table - (e.g.) if 11bit (old protocol) table */
6006       {
6007 	size_t t_i = i-1;
6008 	if (i < gamma_table_raw_size) {
6009 	  DBG (4, "send_gamma: (old protocol) - filling the table.\n");
6010 	  for ( ; i < gamma_table_raw_size; ++ i)
6011 	    gamma_data [i] = gamma_data [t_i];
6012 	}
6013       }
6014 
6015       DBG (4, "send_gamma: sending %lu bytes gamma table.\n",
6016 	   (u_long) gamma_table_raw_size);
6017       status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
6018 			    gamma_data, gamma_table_raw_size, 0, 0);
6019 
6020       if (status != SANE_STATUS_GOOD) {
6021 	DBG (1, "send_gamma: gamma table upload failed: %s\n",
6022 	     sane_strstatus (status));
6023       }
6024     }
6025   free (gamma_data);
6026   return status;
6027 }
6028 
6029 static SANE_Status
send_3x3_matrix(Avision_Scanner * s)6030 send_3x3_matrix (Avision_Scanner* s)
6031 {
6032   SANE_Status status;
6033 
6034 #define SIGN_BIT 0x1000
6035 #define INT_PART 10
6036 
6037   struct matrix_cmd
6038   {
6039     struct command_send scmd;
6040     struct matrix_3x3 matrix;
6041   } cmd;
6042 
6043   /* 04 00  00 00  00 00
6044      00 00  04 00  00 00
6045      00 00  00 00  04 00 */
6046 
6047   int i, a_i;
6048   static const double c5_matrix[] =
6049     { 1.000, 0.000, 0.000,
6050       0.000, 1.000, 0.000,
6051       0.000, 0.000, 1.000 };
6052 
6053   double a_f, b_f;
6054   uint16_t m;
6055 
6056   DBG (3, "send_3x3_matrix:\n");
6057 
6058   memset (&cmd, 0, sizeof (cmd));
6059 
6060   for (i = 0; i < 9; i++)
6061     {
6062       m = 0;
6063       a_f = c5_matrix[i];
6064       if (a_f < 0) {
6065 	m |= SIGN_BIT;
6066 	a_f = -a_f;
6067       }
6068 
6069       a_i = (int) a_f; /* integer */
6070       b_f = a_f - (double) a_i;  /* float */
6071       m |= (uint16_t) ((a_i & 0x3) << INT_PART);
6072       m |= (uint16_t) (b_f * 1024);
6073       set_double (((uint8_t*)(&cmd.matrix.v[i])), m);
6074     }
6075 
6076   cmd.scmd.opc = AVISION_SCSI_SEND;
6077   cmd.scmd.datatypecode = AVISION_DATATYPECODE_3X3_COLOR_MATRIX; /* 0x83 for 3x3 color matrix */
6078   set_triple (cmd.scmd.transferlen, sizeof (struct matrix_3x3));
6079 
6080   if (1) {
6081     DBG (3, "send_3x3_matrix: sending matrix split into two commands\n");
6082     status = avision_cmd (&s->av_con, &cmd.scmd, sizeof (cmd.scmd),
6083                           &cmd.matrix, sizeof(cmd.matrix), 0, 0);
6084   }
6085   else {
6086     DBG (3, "send_3x3_matrix: sending matrix in one command\n");
6087     status = avision_cmd (&s->av_con, &cmd, sizeof (cmd), 0, 0, 0, 0);
6088   }
6089 
6090   return status;
6091 }
6092 
6093 static SANE_Status
get_acceleration_info(Avision_Scanner * s,struct acceleration_info * info)6094 get_acceleration_info (Avision_Scanner* s, struct acceleration_info* info)
6095 {
6096   SANE_Status status;
6097 
6098   struct command_read rcmd;
6099   uint8_t result [24];
6100   size_t size;
6101 
6102   DBG (3, "get_acceleration_info:\n");
6103 
6104   size = sizeof (result);
6105 
6106   memset (&rcmd, 0, sizeof (rcmd));
6107   rcmd.opc = AVISION_SCSI_READ;
6108   rcmd.datatypecode = AVISION_DATATYPECODE_ACCELERATION_TABLE; /* get acceleration information */
6109   set_double (rcmd.datatypequal, s->hw->data_dq);
6110   set_triple (rcmd.transferlen, size);
6111 
6112   DBG (3, "get_acceleration_info: read_data: %lu bytes\n", (u_long) size);
6113   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size);
6114   if (status != SANE_STATUS_GOOD || size != sizeof (result) ) {
6115     status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
6116     DBG (1, "get_acceleration_info: read accel. info failed (%s)\n",
6117 	 sane_strstatus (status) );
6118     return status;
6119   }
6120 
6121   debug_print_accel_info (3, "get_acceleration_info", result);
6122 
6123   info->total_steps = (uint16_t) get_double (&(result[0]));
6124   info->stable_steps = (uint16_t) get_double (&(result[2]));
6125   info->table_units = (uint32_t) get_quad (&(result[4]));
6126   info->base_units = (uint32_t) get_quad (&(result[8]));
6127   info->start_speed = (uint16_t) get_double (&(result[12]));
6128   info->target_speed = (uint16_t) get_double (&(result[14]));
6129   info->ability = result[16];
6130   info->table_count = result[17];
6131 
6132   return SANE_STATUS_GOOD;
6133 }
6134 
6135 static SANE_Status
send_acceleration_table(Avision_Scanner * s)6136 send_acceleration_table (Avision_Scanner* s)
6137 {
6138   SANE_Status status;
6139 
6140   struct command_send scmd;
6141   int table = 0;
6142   int i;
6143   struct acceleration_info accel_info = accel_info;
6144   uint8_t* table_data;
6145 
6146   DBG (3, "send_acceleration_table:\n");
6147 
6148   do {
6149     status = get_acceleration_info (s, &accel_info);
6150 
6151     if (accel_info.table_count == 0) {
6152       DBG (3, "send_acceleration_table: device does not need tables\n");
6153       return SANE_STATUS_GOOD;
6154     }
6155 
6156     if (accel_info.target_speed > accel_info.start_speed ||
6157         accel_info.target_speed == 0 ||
6158         accel_info.total_steps <= accel_info.stable_steps) {
6159       DBG (1, "send_acceleration_table: table does not look right.\n");
6160       return SANE_STATUS_INVAL;
6161     }
6162 
6163     if (accel_info.ability != 0) {
6164       DBG (1, "send_acceleration_table: ability non-zero - insert code\n");
6165       return SANE_STATUS_INVAL;
6166     }
6167 
6168     /* so far I assume we have one byte tables as used in the C6 ASIC ... */
6169     table_data = malloc (accel_info.total_steps + 1000);
6170 
6171     memset (&scmd, 0x00, sizeof (scmd));
6172     scmd.opc = AVISION_SCSI_SEND;
6173     scmd.datatypecode = AVISION_DATATYPECODE_ACCELERATION_TABLE; /* send acceleration table */
6174 
6175     set_double (scmd.datatypequal, table);
6176     set_triple (scmd.transferlen, accel_info.total_steps);
6177 
6178     /* construct the table - Warning: This code is derived from Avision
6179        sample code and is a bit scary! I have no idea why the scanner
6180        needs such a dumb table and also do not know /why/ it has to be
6181        constructed this way. "Works for me" -ReneR */
6182     {
6183       float low_lim = (float) 0.001;
6184       float up_lim  = 1.0;
6185 
6186       uint16_t accel_steps = (uint16_t) (accel_info.total_steps - accel_info.stable_steps + 1);
6187 
6188       /* acceleration ramp */
6189       while ((up_lim - low_lim) > 0.0001)
6190       {
6191 	float mid = (up_lim + low_lim) / 2; /* accel rate */
6192 
6193 	uint16_t now_count = accel_info.start_speed;
6194 
6195 	uint16_t i = 0;
6196 
6197 	float now_count_f = now_count;
6198 	table_data [i++] = (uint8_t) accel_info.start_speed;
6199 
6200 	while (now_count != accel_info.target_speed)
6201 	  {
6202 	    now_count_f = now_count_f - (now_count_f -
6203 					 accel_info.target_speed) * mid;
6204 	    now_count = (uint16_t)(now_count_f + 0.5);
6205 	    table_data[i++] = (uint8_t) now_count;
6206 	  }
6207 
6208 
6209 	if (i == accel_steps)
6210 	  break;
6211 	if (i > accel_steps)
6212 	  low_lim = mid;
6213 	else
6214 	  up_lim = mid;
6215       }
6216 
6217       /* fill stable steps */
6218       for (i = accel_steps; i < accel_info.total_steps; i++)
6219 	  table_data [i] = table_data [i-1];
6220 
6221       debug_print_hex_raw (5, "send_acceleration_table: first pass:\n",
6222 			   table_data, accel_info.total_steps);
6223 
6224       /* maybe post fix-up */
6225       {
6226 	int add_count;
6227 
6228 	/* count total steps in table */
6229 	uint32_t table_total = 0;
6230 	for (i = 0; i < accel_info.total_steps; i++)
6231 	  table_total += table_data [i];
6232 
6233 	i = 0;
6234 	if (((table_total * accel_info.table_units) % accel_info.base_units) == 0)
6235 	  add_count = 0;
6236 	else
6237 	  add_count = (int) ((accel_info.base_units -
6238                       ((table_total*accel_info.table_units) % accel_info.base_units))
6239 	    / accel_info.table_units);
6240 
6241 	/* add_count should not be bigger than 255 */
6242 	if (add_count > 255) {
6243 	  DBG (1, "send_acceleration_table: add_count limited, was: %d\n", add_count);
6244 	  add_count = 255;
6245 	}
6246 	for (i = 0; i < accel_info.total_steps - 1 && add_count > 0; i++)
6247 	  {
6248 	    uint16_t temp_count = 255 - table_data [i];
6249 	    temp_count = (uint16_t) (temp_count > add_count ? add_count : temp_count);
6250 
6251 	    table_data [i] += (uint8_t) temp_count;
6252 	    add_count -= temp_count;
6253 	  }
6254       }
6255     }
6256 
6257     debug_print_hex_raw (5, "send_acceleration_table: fixed up:\n",
6258 			 table_data, accel_info.total_steps);
6259 
6260     /* decrease all by one ... */
6261     for (i = 0; i < accel_info.total_steps; i++) {
6262       table_data[i]--;
6263     }
6264 
6265     DBG (1, "send_acceleration_table: sending table %d\n", table);
6266 
6267     debug_print_hex_raw (5, "send_acceleration_table: final:\n",
6268 			 table_data, accel_info.total_steps);
6269 
6270     status = avision_cmd (&s->av_con, &scmd, sizeof (scmd),
6271 			  (char*) table_data, accel_info.total_steps,
6272 			  0, 0);
6273     if (status != SANE_STATUS_GOOD) {
6274       DBG (3, "send_acceleration_table: send_data failed (%s)\n",
6275 	   sane_strstatus (status));
6276     }
6277 
6278     free (table_data); table_data = 0;
6279 
6280     table++;
6281   } while (table < accel_info.table_count);
6282 
6283 
6284   return status;
6285 }
6286 
6287 static SANE_Status
set_window(Avision_Scanner * s)6288 set_window (Avision_Scanner* s)
6289 {
6290   Avision_Device* dev = s->hw;
6291   SANE_Status status;
6292   int base_dpi_abs, base_dpi_rel;
6293   size_t transferlen;
6294   size_t paralen;
6295 
6296   int bytes_per_line;
6297   int line_count;
6298 
6299   struct {
6300     struct command_set_window cmd;
6301     struct command_set_window_window window;
6302   } cmd;
6303 
6304   DBG (1, "set_window:\n");
6305 
6306   /* plain old scanners, the C3 ASIC HP 53xx and the C6 ASIC HP 74xx
6307      and up do use 1200 as base - only the C5 differs */
6308   switch (dev->inquiry_asic_type) {
6309   case AV_ASIC_C5:
6310     base_dpi_abs = 1200;
6311     /* round down to the next multiple of 300 */
6312     base_dpi_rel = s->avdimen.hw_xres - s->avdimen.hw_xres % 300;
6313     if (base_dpi_rel > dev->inquiry_optical_res)
6314       base_dpi_rel = dev->inquiry_optical_res;
6315     else if (s->avdimen.hw_xres <= 150)
6316       base_dpi_rel = 150;
6317     break;
6318   default:
6319     base_dpi_abs = 1200;
6320     base_dpi_rel = 1200;
6321   }
6322 
6323   DBG (2, "set_window: base_dpi_abs: %d, base_dpi_rel: %d\n", base_dpi_abs, base_dpi_rel);
6324 
6325   /* wipe out anything */
6326   memset (&cmd, 0, sizeof (cmd) );
6327   cmd.window.descriptor.winid = AV_WINID; /* normally defined to be zero */
6328 
6329   /* optional parameter length to use */
6330   paralen = sizeof (cmd.window.avision) - sizeof (cmd.window.avision.type);
6331 
6332   DBG (2, "set_window: base paralen: %zu\n", paralen);
6333 
6334   if (dev->hw->feature_type & AV_FUJITSU)
6335     paralen += sizeof (cmd.window.avision.type.fujitsu);
6336   else if (!dev->inquiry_new_protocol)
6337     paralen += sizeof (cmd.window.avision.type.old);
6338   else if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN)
6339     paralen += sizeof (cmd.window.avision.type.normal);
6340   else
6341     paralen += sizeof (cmd.window.avision.type.normal) - 1;
6342 
6343   DBG (2, "set_window: final paralen: %zu\n", paralen);
6344 
6345   transferlen = sizeof (cmd.window)
6346     - sizeof (cmd.window.avision) + paralen;
6347 
6348   DBG (2, "set_window: transferlen: %zu\n", transferlen);
6349 
6350   /* command setup */
6351   cmd.cmd.opc = AVISION_SCSI_SET_WINDOW;
6352   set_triple (cmd.cmd.transferlen, transferlen);
6353   set_double (cmd.window.header.desclen,
6354 	      sizeof (cmd.window.descriptor) + paralen);
6355 
6356   /* resolution parameters */
6357   set_double (cmd.window.descriptor.xres, s->avdimen.hw_xres);
6358   set_double (cmd.window.descriptor.yres, s->avdimen.hw_yres);
6359 
6360   /* upper left corner x/y as well as width/length in inch * base_dpi
6361      - avdimen are world pixels */
6362   set_quad (cmd.window.descriptor.ulx, s->avdimen.tlx * base_dpi_abs / s->avdimen.hw_xres);
6363   set_quad (cmd.window.descriptor.uly, s->avdimen.tly * base_dpi_abs / s->avdimen.hw_yres);
6364 
6365   set_quad (cmd.window.descriptor.width,
6366 	    s->avdimen.hw_pixels_per_line * base_dpi_rel / s->avdimen.hw_xres + 1);
6367   line_count = s->avdimen.hw_lines + 2 * s->avdimen.line_difference;
6368   set_quad (cmd.window.descriptor.length,
6369 	    line_count * base_dpi_rel / s->avdimen.hw_yres + 1);
6370 
6371   /* interlaced duplex scans are twice as long */
6372   if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) {
6373     DBG (2, "set_window: interlaced duplex scan, doubled line count\n");
6374     line_count *= 2;
6375   }
6376 
6377   bytes_per_line = s->avdimen.hw_bytes_per_line;
6378 
6379   set_double (cmd.window.avision.line_width, bytes_per_line);
6380   set_double (cmd.window.avision.line_count, line_count);
6381 
6382   /* here go the most significant bits if bigger than 16 bit */
6383   if (dev->inquiry_new_protocol && !(dev->hw->feature_type & AV_FUJITSU) ) {
6384     DBG (2, "set_window: large data-transfer support (>16bit)!\n");
6385     cmd.window.avision.type.normal.line_width_msb = (uint8_t)
6386       (bytes_per_line >> 16);
6387     cmd.window.avision.type.normal.line_count_msb = (uint8_t)
6388       (line_count >> 16);
6389   }
6390 
6391   if (dev->inquiry_background_raster)
6392     cmd.window.avision.type.normal.background_lines = (uint8_t) s->val[OPT_BACKGROUND].w;
6393 
6394   /* scanner should use our line-width and count */
6395   SET_BIT (cmd.window.avision.bitset1, 6);
6396 
6397   /* set speed */
6398   cmd.window.avision.bitset1 |= (uint8_t) (s->val[OPT_SPEED].w & 0x07); /* only 3 bit */
6399 
6400   /* ADF scan? */
6401   DBG (3, "set_window: source mode %d source mode dim %d\n",
6402        s->source_mode, s->source_mode_dim);
6403 
6404   if (s->source_mode == AV_ADF ||
6405       s->source_mode == AV_ADF_REAR ||
6406       s->source_mode == AV_ADF_DUPLEX) {
6407     DBG (3, "set_window: filling ADF bits\n");
6408     SET_BIT (cmd.window.avision.bitset1, 7);
6409 
6410     if (dev->hw->feature_type & AV_MULTI_SHEET_SCAN) {
6411       /* Always set bit 7 to enable single_sheet_scan option (defaults to off).
6412          This removes the 1s pause between two sheets and fixes some offsets. */
6413       SET_BIT(cmd.window.avision.type.normal.bitset3, 7);
6414       cmd.window.avision.type.normal.single_sheet_scan = 0;
6415     }
6416 
6417     /* normal, interlaced duplex scanners */
6418     if (dev->inquiry_duplex_interlaced) {
6419       DBG (3, "set_window: interlaced duplex type\n");
6420       if (s->source_mode == AV_ADF_REAR) {
6421         SET_BIT(cmd.window.avision.type.normal.bitset3, 3); /* 0x08 */
6422       }
6423       if (s->source_mode == AV_ADF_DUPLEX) {
6424         SET_BIT(cmd.window.avision.type.normal.bitset3, 4); /* 0x10 */
6425       }
6426     }
6427     else if (s->source_mode == AV_ADF_DUPLEX) /* HP 2-pass duplex */
6428     {
6429       DBG (3, "set_window: non-interlaced duplex type (HP)\n");
6430       SET_BIT(cmd.window.avision.type.normal.bitset3, 0); /* DPLX 0x01 */
6431       if (s->val[OPT_ADF_FLIP].w)
6432         SET_BIT(cmd.window.avision.type.normal.bitset3, 1); /* FLIP 0x02 */
6433       SET_BIT(cmd.window.avision.type.normal.bitset3, 2); /* MIRR 0x04 */
6434     }
6435   }
6436 
6437   if (s->val[OPT_PAPERLEN].w != SANE_FALSE) {
6438      set_double (cmd.window.descriptor.paper_length, (int)((double)30.0*1200));
6439   }
6440 
6441   if ( !(dev->hw->feature_type & AV_FUJITSU) )
6442     {
6443       /* quality scan option switch */
6444       if (s->val[OPT_QSCAN].w == SANE_TRUE &&
6445           !(dev->hw->feature_type & AV_NO_QSCAN_MODE)) {
6446 	SET_BIT (cmd.window.avision.type.normal.bitset2, 4);
6447       }
6448 
6449       /* quality calibration option switch (inverted! if set == speed) */
6450       if (s->val[OPT_QCALIB].w == SANE_FALSE &&
6451           !(dev->hw->feature_type & AV_NO_QCALIB_MODE)) {
6452 	SET_BIT (cmd.window.avision.type.normal.bitset2, 3);
6453       }
6454 
6455       /* transparency option switch */
6456       if (s->source_mode_dim == AV_TRANSPARENT_DIM) {
6457 	SET_BIT (cmd.window.avision.type.normal.bitset2, 7);
6458       }
6459 
6460       if (dev->scanner_type == AV_FILM) {
6461 	/* TODO: wire to IR exposure option? */
6462 	cmd.window.avision.type.normal.ir_exposure_time = 100;
6463 	set_double (cmd.window.avision.type.normal.r_exposure_time, s->val[OPT_EXPOSURE].w);
6464 	set_double (cmd.window.avision.type.normal.g_exposure_time, s->val[OPT_EXPOSURE].w);
6465 	set_double (cmd.window.avision.type.normal.b_exposure_time, s->val[OPT_EXPOSURE].w);
6466 
6467 	if (s->val[OPT_IR].w)
6468 	  cmd.window.avision.type.normal.bitset3 |= (1 << 0);
6469 
6470 	if (s->val[OPT_MULTISAMPLE].w)
6471 	  cmd.window.avision.type.normal.bitset3 |= (1 << 1);
6472       }
6473     }
6474 
6475   /* fixed values */
6476   cmd.window.descriptor.padding_and_bitset = 3;
6477   cmd.window.descriptor.vendor_specific = 0xFF;
6478   cmd.window.descriptor.paralen = (uint8_t) paralen; /* R² was: 9, later 14 */
6479 
6480   /* This is normally unsupported by Avision scanners, and we do this
6481      via the gamma table - which works for all devices ... */
6482   cmd.window.descriptor.threshold = 128;
6483   cmd.window.descriptor.brightness = 128;
6484   cmd.window.descriptor.contrast = 128;
6485   cmd.window.avision.highlight = 0xFF;
6486   cmd.window.avision.shadow = 0x00;
6487 
6488   /* mode dependent settings */
6489   switch (s->c_mode)
6490     {
6491     case AV_THRESHOLDED:
6492       cmd.window.descriptor.bpc = 1;
6493       cmd.window.descriptor.image_comp = 0;
6494       break;
6495 
6496     case AV_DITHERED:
6497       cmd.window.descriptor.bpc = 1;
6498       cmd.window.descriptor.image_comp = 1;
6499       break;
6500 
6501     case AV_GRAYSCALE:
6502       cmd.window.descriptor.bpc = 8;
6503       cmd.window.descriptor.image_comp = 2;
6504       break;
6505 
6506     case AV_GRAYSCALE12:
6507       cmd.window.descriptor.bpc = 12;
6508       cmd.window.descriptor.image_comp = 2;
6509       break;
6510 
6511     case AV_GRAYSCALE16:
6512       cmd.window.descriptor.bpc = 16;
6513       cmd.window.descriptor.image_comp = 2;
6514       break;
6515 
6516     case AV_TRUECOLOR:
6517       cmd.window.descriptor.bpc = 8;
6518       cmd.window.descriptor.image_comp = 5;
6519       break;
6520 
6521     case AV_TRUECOLOR12:
6522       cmd.window.descriptor.bpc = 12;
6523       cmd.window.descriptor.image_comp = 5;
6524       break;
6525 
6526     case AV_TRUECOLOR16:
6527       cmd.window.descriptor.bpc = 16;
6528       cmd.window.descriptor.image_comp = 5;
6529       break;
6530 
6531     default:
6532       DBG (1, "Invalid mode. %d\n", s->c_mode);
6533       return SANE_STATUS_INVAL;
6534     }
6535 
6536   if (color_mode_is_color (s->c_mode)) {
6537     cmd.window.avision.bitset1 |= AVISION_FILTER_RGB;
6538   }
6539   else {
6540     if (dev->hw->feature_type & AV_FASTER_WITH_FILTER)
6541       cmd.window.avision.bitset1 |= AVISION_FILTER_GREEN;
6542     else if (dev->hw->feature_type & AV_USE_GRAY_FILTER)
6543       cmd.window.avision.bitset1 |= AVISION_FILTER_GRAY;
6544     else
6545       cmd.window.avision.bitset1 |= AVISION_FILTER_NONE;
6546   }
6547 
6548   debug_print_window_descriptor (5, "set_window", &(cmd.window));
6549 
6550   DBG (3, "set_window: sending command. Bytes: %zu\n", transferlen);
6551   status = avision_cmd (&s->av_con, &cmd, sizeof (cmd.cmd),
6552 			&(cmd.window), transferlen, 0, 0);
6553 
6554   return status;
6555 }
6556 
6557 static SANE_Status
get_background_raster(Avision_Scanner * s)6558 get_background_raster (Avision_Scanner* s)
6559 {
6560   const int debug = 0;
6561 
6562   Avision_Device* dev = s->hw;
6563   SANE_Status status;
6564 
6565   struct command_read rcmd;
6566   size_t size;
6567   int bytes_per_line, i;
6568   const int bpp = color_mode_is_color (s->c_mode) ? 3 : 1;
6569   const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1);
6570 
6571   uint8_t* background = NULL;
6572 
6573   DBG (1, "get_background_raster:\n");
6574 
6575   if (lines == 0) {
6576     DBG (1, "get_background_raster: no background requested\n");
6577     return SANE_STATUS_GOOD;
6578   }
6579 
6580   /* full width, always :-(, duplex *2 for front and rear */
6581   bytes_per_line = dev->inquiry_background_raster_pixel *
6582     s->avdimen.hw_xres / dev->inquiry_optical_res;
6583   bytes_per_line *= bpp;
6584 
6585   DBG (3, "get_background_raster: native raster pixels: %d, raster bytes_per_line: %d\n",
6586        dev->inquiry_background_raster_pixel, bytes_per_line);
6587 
6588   /* according to spec only 8-bit gray or color, TODO: test for bi-level scans */
6589   size = (size_t) bytes_per_line * (size_t) lines;
6590 
6591   DBG (3, "get_background_raster: buffer size: %ld\n", (long)size);
6592 
6593   background = s->background_raster = realloc (s->background_raster, size);
6594   if (!background)
6595     return SANE_STATUS_NO_MEM;
6596 
6597   memset (&rcmd, 0, sizeof (rcmd));
6598   rcmd.opc = AVISION_SCSI_READ;
6599   rcmd.datatypecode = AVISION_DATATYPECODE_GET_BACKGROUND_RASTER; /* get background raster */
6600   set_double (rcmd.datatypequal, s->hw->data_dq);
6601 
6602   /* Ok, well - this part is very messy. The AV122 and DM152 appear to
6603      contain differently buggy ASICs. The only combination I found to
6604      at least get a correct front raster out of them is to read it
6605      line by line and then every second line appears to be valid front
6606      data, ... */
6607 
6608   /* read the raster data */
6609   for (i = 0; i < lines;)
6610     {
6611       uint8_t* dst_raster = background + bytes_per_line * i;
6612       /* read stripe by stripe, or all in one chunk */
6613       size_t this_read, read_size;
6614       int this_lines;
6615 
6616       if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) {
6617 	if (dev->hw->feature_type & AV_BACKGROUND_QUIRK)
6618 	  this_lines = 1;
6619 	else
6620 	  this_lines = lines;
6621       }
6622       else {
6623 	this_lines = s->val[OPT_BACKGROUND].w;
6624       }
6625       this_read = (size_t) bytes_per_line * (size_t) this_lines;
6626 
6627       DBG (3, "get_background_raster: line: %d, lines: %d, %lu bytes\n",
6628 	   i, this_lines, (u_long) this_read);
6629 
6630       set_triple (rcmd.transferlen, this_read);
6631 
6632       read_size = this_read;
6633       status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size);
6634       if (status != SANE_STATUS_GOOD || read_size != this_read) {
6635 	status = (status != SANE_STATUS_GOOD)? status: SANE_STATUS_IO_ERROR;
6636 	DBG (1, "get_background_raster: read raster failed (%s)\n", sane_strstatus (status) );
6637 	return status;
6638       }
6639 
6640       i += this_lines;
6641     }
6642 
6643   /* dump raw result while debugging */
6644   if (debug)
6645     {
6646       FILE* f = NULL;
6647       f = fopen ("background-raw.pnm", "w");
6648 
6649       write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6650 			bytes_per_line / bpp, lines);
6651 
6652       fwrite (background, 1, (size_t) bytes_per_line * (size_t) lines, f);
6653       fclose (f);
6654     }
6655 
6656   /* line-pack - move to unified processing flow, later */
6657   if (dev->inquiry_needs_line_pack)
6658     {
6659       /* TODO: add 16bit per sample code? */
6660       int l, p;
6661 
6662       uint8_t* tmp_data = malloc ((size_t) bytes_per_line);
6663       for (l = 0; l < lines; ++l)
6664 	{
6665 	  uint8_t* out_data = tmp_data;
6666 	  uint8_t* r_ptr = background + (bytes_per_line * l);
6667 	  uint8_t* g_ptr = r_ptr + bytes_per_line / bpp;
6668 	  uint8_t* b_ptr = g_ptr + bytes_per_line / bpp;
6669 
6670 	  for (p = 0; p < bytes_per_line;) {
6671 	    out_data [p++] = *(r_ptr++);
6672 	    out_data [p++] = *(g_ptr++);
6673 	    out_data [p++] = *(b_ptr++);
6674 	  }
6675 
6676 	  memcpy (background + (bytes_per_line * l), tmp_data, (size_t) bytes_per_line);
6677 	}
6678 
6679       free (tmp_data);
6680     } /* end line pack */
6681 
6682   /* deinterlace? */
6683   if (s->avdimen.interlaced_duplex && (dev->hw->feature_type & AV_2ND_LINE_INTERLACED))
6684     {
6685       uint8_t* deinterlaced = malloc (size * 2);
6686       if (!deinterlaced)
6687 	return SANE_STATUS_NO_MEM;
6688 
6689       for (i = 0; i < lines; ++i)
6690 	{
6691 	  int dst_i = i / 2 + (i % 2) * (lines / 2);
6692 	  uint8_t* dst_raster; /* just no C99 in SANE :-( */
6693 	  uint8_t* src_raster;
6694 
6695 	  /* for the quirky devices and some resolutions the interlacing differs */
6696 	  if ((dev->hw->feature_type & AV_BACKGROUND_QUIRK) && (s->avdimen.hw_xres >= 150))
6697 	    dst_i = i / 2 + ((i+1) % 2) * (lines / 2);
6698 
6699 	  dst_raster = deinterlaced + bytes_per_line * dst_i;
6700 	  src_raster = background + bytes_per_line * i;
6701 
6702 	  DBG(3, "get_background_raster: deinterlaced %d -> %d\n", i, dst_i);
6703 	  memcpy(dst_raster, src_raster, (size_t) bytes_per_line);
6704 	}
6705 
6706       free (background);
6707       background = s->background_raster = deinterlaced;
6708     }
6709 
6710   /* dump raw result while debugging */
6711   for (i = 0; debug && i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i)
6712     {
6713     FILE* f = NULL;
6714     uint8_t* raster = background;
6715     if (i == 0) {
6716       f = fopen ("background.pnm", "w");
6717     }
6718     else {
6719       f = fopen ("background-rear.pnm", "w");
6720       raster += bytes_per_line * s->val[OPT_BACKGROUND].w;
6721     }
6722 
6723     write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6724 		      bytes_per_line / bpp, s->val[OPT_BACKGROUND].w);
6725 
6726     fwrite (raster, 1, (size_t) bytes_per_line * (size_t) s->val[OPT_BACKGROUND].w, f);
6727     fclose (f);
6728   }
6729 
6730   /* crop from full-width scanlines to scan window */
6731   {
6732     uint8_t *dst_ptr, *src_ptr;
6733     dst_ptr = background;
6734     src_ptr = background + s->avdimen.tlx * bpp;
6735     for (i = 0; i < lines; ++i)
6736       {
6737 	memmove (dst_ptr, src_ptr, (size_t) s->avdimen.hw_bytes_per_line);
6738 	dst_ptr += s->avdimen.hw_bytes_per_line;
6739 	src_ptr += bytes_per_line;
6740       }
6741   }
6742 
6743   /* soft-scale - move to unified processing flow, later */
6744   if (s->avdimen.hw_xres != s->avdimen.xres)
6745     {
6746       const uint8_t* out_data = background;
6747       uint8_t* dst = background;
6748 
6749       int l;
6750       for (l = 0; l < lines; ++l)
6751 	{
6752 	  const int hwbpl = s->avdimen.hw_bytes_per_line;
6753 	  const int sy = l;
6754 
6755 	  int x;
6756 	  for (x = 0; x < s->params.pixels_per_line; ++x)
6757 	    {
6758 	      const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line;
6759 	      const int sx = (int)floor(bx);
6760 	      const int xdist = (int) ((bx - sx) * 256);
6761 	      const int sxx = sx + 1;
6762 
6763 	      switch (bpp) {
6764 	      case 1:
6765 		{
6766 		  uint8_t v = (uint8_t)
6767 		    (( out_data [sy*hwbpl  + sx ] * (256-xdist) +
6768 		      out_data [sy*hwbpl  + sxx] * xdist
6769 		    ) / (256));
6770 		  *dst++ = v;
6771 		}
6772 		break;
6773 
6774 	      case 3:
6775 		{
6776 		  int c;
6777 		  for (c = 0; c < 3; ++c)
6778 		    {
6779 		      uint8_t v = (uint8_t)
6780 			(( out_data [sy*hwbpl  + sx*3  + c] * (256-xdist) +
6781 			  out_data [sy*hwbpl  + sxx*3 + c] * xdist
6782 			  ) / (256));
6783 		      *dst++ = v;
6784 		    }
6785 		}
6786 		break;
6787 	      }
6788 	    }
6789 	}
6790     }
6791 
6792   /* dump final result while debugging */
6793   if (debug) {
6794     for (i = 0; i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i)
6795       {
6796 	FILE* f = NULL;
6797 	uint8_t* raster = background;
6798 	if (i == 0) {
6799 	  f = fopen ("background-final.pnm", "w");
6800 	}
6801 	else {
6802 	  f = fopen ("background-final-rear.pnm", "w");
6803 	  raster += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w;
6804 	}
6805 
6806 	write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8,
6807 			  s->params.bytes_per_line / bpp, s->val[OPT_BACKGROUND].w);
6808 
6809 	fwrite (raster, 1, (size_t) s->params.bytes_per_line * (size_t) s->val[OPT_BACKGROUND].w, f);
6810 	fclose (f);
6811       }
6812   }
6813 
6814   return SANE_STATUS_GOOD;
6815 }
6816 
6817 static SANE_Status
reserve_unit(Avision_Scanner * s)6818 reserve_unit (Avision_Scanner* s)
6819 {
6820   char cmd[] =
6821     {AVISION_SCSI_RESERVE_UNIT, 0, 0, 0, 0, 0};
6822   SANE_Status status;
6823 
6824   DBG (1, "reserve_unit:\n");
6825 
6826   status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0);
6827   return status;
6828 }
6829 
6830 static SANE_Status
release_unit(Avision_Scanner * s,int type)6831 release_unit (Avision_Scanner* s, int type)
6832 {
6833   char cmd[] =
6834     {AVISION_SCSI_RELEASE_UNIT, 0, 0, 0, 0, 0};
6835   SANE_Status status;
6836 
6837   DBG (1, "release unit: type: %d\n", type);
6838   cmd[5] = (char) type; /* latest scanners also allow 1: release paper and 2: end job */
6839   status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0);
6840   return status;
6841 }
6842 
6843 /* Check if a sheet is present. */
6844 static SANE_Status
media_check(Avision_Scanner * s)6845 media_check (Avision_Scanner* s)
6846 {
6847   char cmd[] = {AVISION_SCSI_MEDIA_CHECK, 0, 0, 0, 1, 0}; /* 1, 4 */
6848   SANE_Status status;
6849   uint8_t result[1]; /* 4 */
6850   size_t size = sizeof(result);
6851 
6852   status = avision_cmd (&s->av_con, cmd, sizeof (cmd),
6853 			0, 0, result, &size);
6854 
6855   debug_print_raw (5, "media_check: result\n", result, size);
6856 
6857   if (status == SANE_STATUS_GOOD) {
6858     if (!(result[0] & 0x1))
6859       status = SANE_STATUS_NO_DOCS;
6860   }
6861 
6862   return status;
6863 }
6864 
6865 #if 0 /* unused */
6866 static SANE_Status
6867 flush_media (Avision_Scanner* s)
6868 {
6869   Avision_Device* dev = s->hw;
6870   SANE_Status status;
6871 
6872   if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_batch_scan)
6873     {
6874       DBG (1, "flush_media: flushing pages out of batch scanner\n");
6875       do {
6876 	status = media_check (s);
6877 	if (status == SANE_STATUS_GOOD) {
6878 	  SANE_Status status2 = reserve_unit (s);
6879 	  DBG (1, "flush_media: reserve status: %d\n", status2);
6880 	  status2 = release_unit (s, 0);
6881 	  DBG (1, "flush_media: release status: %d\n", status2);
6882 	}
6883       } while (status == SANE_STATUS_GOOD);
6884     }
6885   return SANE_STATUS_GOOD;
6886 }
6887 #endif /* 0 - unused */
6888 
6889 static SANE_Status
object_position(Avision_Scanner * s,uint8_t position)6890 object_position (Avision_Scanner* s, uint8_t position)
6891 {
6892   SANE_Status status;
6893 
6894   uint8_t cmd [10];
6895 
6896   memset (cmd, 0, sizeof (cmd));
6897   cmd[0] = AVISION_SCSI_OBJECT_POSITION;
6898   cmd[1] = position;
6899 
6900   DBG (1, "object_position: %d\n", position);
6901 
6902   status = avision_cmd (&s->av_con, cmd, sizeof(cmd), 0, 0, 0, 0);
6903   return status;
6904 }
6905 
6906 static SANE_Status
start_scan(Avision_Scanner * s)6907 start_scan (Avision_Scanner* s)
6908 {
6909   struct command_scan cmd;
6910 
6911   size_t size = sizeof (cmd);
6912 
6913   DBG (3, "start_scan:\n");
6914 
6915   memset (&cmd, 0, sizeof (cmd));
6916   cmd.opc = AVISION_SCSI_SCAN;
6917   cmd.transferlen = 1;
6918 
6919   /* AV610C2 in ADF preview mode does not detect the page end (...) */
6920   if (s->val[OPT_PREVIEW].w == SANE_TRUE && s->hw->inquiry_asic_type != AV_ASIC_C7) {
6921     SET_BIT(cmd.bitset1,6);
6922   }
6923 
6924   if (s->val[OPT_QSCAN].w == SANE_TRUE &&
6925       !(s->hw->hw->feature_type & AV_NO_QSCAN_MODE)) {
6926     SET_BIT(cmd.bitset1,7);
6927   }
6928 
6929   DBG (3, "start_scan: sending command. Bytes: %lu\n", (u_long) size);
6930   return avision_cmd (&s->av_con, &cmd, size, 0, 0, 0, 0);
6931 }
6932 
6933 static SANE_Status
do_eof(Avision_Scanner * s)6934 do_eof (Avision_Scanner *s)
6935 {
6936   int exit_status;
6937 
6938   DBG (3, "do_eof:\n");
6939 
6940   /* we do not scan anymore */
6941   s->prepared = s->scanning = SANE_FALSE;
6942 
6943   /* we can now mark the rear data as valid */
6944   if (s->avdimen.interlaced_duplex ||
6945       (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) {
6946     DBG (3, "do_eof: toggling duplex rear data valid\n");
6947     s->duplex_rear_valid = !s->duplex_rear_valid;
6948     DBG (3, "do_eof: duplex rear data valid: %x\n",
6949 	 s->duplex_rear_valid);
6950   }
6951 
6952   if (s->read_fds >= 0) {
6953     close (s->read_fds);
6954     s->read_fds = -1;
6955   }
6956 
6957   /* join our processes - without a wait() you will produce zombies
6958      (defunct children) */
6959   sanei_thread_waitpid (s->reader_pid, &exit_status);
6960   sanei_thread_invalidate (s->reader_pid);
6961 
6962   DBG (3, "do_eof: returning %d\n", exit_status);
6963   return (SANE_Status)exit_status;
6964 }
6965 
6966 static SANE_Status
do_cancel(Avision_Scanner * s)6967 do_cancel (Avision_Scanner* s)
6968 {
6969   int status;
6970 
6971   DBG (3, "do_cancel:\n");
6972 
6973   s->prepared = s->scanning = SANE_FALSE;
6974   s->duplex_rear_valid = SANE_FALSE;
6975   s->page = 0;
6976   s->cancelled = SANE_TRUE;
6977 
6978   if (s->read_fds >= 0) {
6979     close(s->read_fds);
6980     s->read_fds = -1;
6981   }
6982 
6983   if (sanei_thread_is_valid (s->reader_pid)) {
6984     int exit_status;
6985 
6986     /* ensure child knows it's time to stop: */
6987     sanei_thread_kill (s->reader_pid);
6988     sanei_thread_waitpid (s->reader_pid, &exit_status);
6989     sanei_thread_invalidate (s->reader_pid);
6990   }
6991 
6992   if (s->hw->hw->feature_type & AV_FASTFEED_ON_CANCEL) {
6993     status = release_unit (s, 1);
6994     if (status != SANE_STATUS_GOOD)
6995       DBG (1, "do_cancel: release_unit failed\n");
6996   }
6997 
6998   DBG (4, "FORCE RELEASE UNIT ON CANCEL\n");
6999   status = release_unit (s, 1);
7000   if (status != SANE_STATUS_GOOD)
7001     DBG (1, "do_cancel: release_unit failed\n");
7002 
7003   return SANE_STATUS_CANCELLED;
7004 }
7005 
7006 static SANE_Status
read_data(Avision_Scanner * s,SANE_Byte * buf,size_t * count)7007 read_data (Avision_Scanner* s, SANE_Byte* buf, size_t* count)
7008 {
7009   struct command_read rcmd;
7010   SANE_Status status;
7011 
7012   DBG (9, "read_data: %lu\n", (u_long) *count);
7013 
7014   memset (&rcmd, 0, sizeof (rcmd));
7015 
7016   rcmd.opc = AVISION_SCSI_READ;
7017   rcmd.datatypecode = AVISION_DATATYPECODE_READ_IMAGE_DATA; /* read image data */
7018   set_double (rcmd.datatypequal, s->hw->data_dq);
7019   set_triple (rcmd.transferlen, *count);
7020 
7021   status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, buf, count);
7022 
7023   return status;
7024 }
7025 
7026 static SANE_Status
init_options(Avision_Scanner * s)7027 init_options (Avision_Scanner* s)
7028 {
7029   Avision_Device* dev = s->hw;
7030   int i;
7031 
7032   DBG (3, "init_options:\n");
7033 
7034   memset (s->opt, 0, sizeof (s->opt));
7035   memset (s->val, 0, sizeof (s->val));
7036 
7037   /*
7038    * Set defaults for all the options.
7039    *
7040    */
7041   for (i = 0; i < NUM_OPTIONS; ++i)
7042     {
7043       s->opt[i].name = "";
7044       s->opt[i].desc = "";
7045       s->opt[i].unit = SANE_UNIT_NONE;
7046       s->opt[i].size = sizeof(SANE_Word);
7047       s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
7048     }
7049 
7050   /* Init the SANE option from the scanner inquiry data */
7051 
7052   switch (dev->inquiry_asic_type) {
7053     case AV_ASIC_C2:
7054       dev->dpi_range.min = 100;
7055       break;
7056     case AV_ASIC_C5:
7057       dev->dpi_range.min = 80;
7058       break;
7059     case AV_ASIC_C6: /* TODO: AV610 in ADF mode does not scan less than 180 or so; */
7060                      /* Scanjet 8250 does not work with 50 in normal mode */
7061       dev->dpi_range.min = 60;
7062       break;
7063     case AV_ASIC_C7: /* AV610C2 empirically tested out */
7064       dev->dpi_range.min = 75;
7065       break;
7066     default:
7067       dev->dpi_range.min = 50;
7068   }
7069   DBG (1, "init_options: dpi_range.min set to %d\n", dev->dpi_range.min);
7070 
7071   dev->dpi_range.quant = 1; /* any, including 72, 144, etc. */
7072   dev->dpi_range.max = dev->inquiry_max_res;
7073 
7074   dev->speed_range.min = (SANE_Int)0;
7075   dev->speed_range.max = (SANE_Int)4;
7076   dev->speed_range.quant = (SANE_Int)1;
7077 
7078   s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
7079   s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
7080   s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
7081   s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT);
7082   s->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
7083 
7084   /* "Mode" group: */
7085   s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE;
7086   s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
7087   s->opt[OPT_MODE_GROUP].cap = 0;
7088   s->opt[OPT_MODE_GROUP].size = 0;
7089   s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7090 
7091   /* color mode */
7092   s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
7093   s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
7094   s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
7095   s->opt[OPT_MODE].type = SANE_TYPE_STRING;
7096   s->opt[OPT_MODE].size = (SANE_Int) max_string_size (dev->color_list);
7097   s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
7098   s->opt[OPT_MODE].constraint.string_list = dev->color_list;
7099   s->val[OPT_MODE].s = strdup (dev->color_list[dev->color_list_default]);
7100   s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s);
7101 
7102   /* source mode */
7103   s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
7104   s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
7105   s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
7106   s->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
7107   s->opt[OPT_SOURCE].size = (SANE_Int) max_string_size(dev->source_list);
7108   s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
7109   s->opt[OPT_SOURCE].constraint.string_list = &dev->source_list[0];
7110   s->val[OPT_SOURCE].s = strdup(dev->source_list[0]);
7111   s->source_mode = match_source_mode (dev, s->val[OPT_SOURCE].s);
7112   s->source_mode_dim = match_source_mode_dim (s->source_mode);
7113 
7114   dev->x_range.max = SANE_FIX ( (int)dev->inquiry_x_ranges[s->source_mode_dim]);
7115   dev->x_range.quant = 0;
7116   dev->y_range.max = SANE_FIX ( (int)dev->inquiry_y_ranges[s->source_mode_dim]);
7117   dev->y_range.quant = 0;
7118 
7119   /* resolution */
7120   s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
7121   s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
7122   s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
7123   s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
7124   s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
7125   s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
7126   s->opt[OPT_RESOLUTION].constraint.range = &dev->dpi_range;
7127   s->val[OPT_RESOLUTION].w = OPT_RESOLUTION_DEFAULT;
7128 
7129   /* preview */
7130   s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
7131   s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
7132   s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
7133   s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT;
7134   s->val[OPT_PREVIEW].w = 0;
7135 
7136   /* speed option */
7137   s->opt[OPT_SPEED].name  = SANE_NAME_SCAN_SPEED;
7138   s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED;
7139   s->opt[OPT_SPEED].desc  = SANE_DESC_SCAN_SPEED;
7140   s->opt[OPT_SPEED].type  = SANE_TYPE_INT;
7141   s->opt[OPT_SPEED].constraint_type  = SANE_CONSTRAINT_RANGE;
7142   s->opt[OPT_SPEED].constraint.range = &dev->speed_range;
7143   s->val[OPT_SPEED].w = 0;
7144   if (dev->scanner_type == AV_SHEETFEED)
7145     s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE;
7146 
7147   /* "Geometry" group: */
7148   s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
7149   s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
7150   s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
7151   s->opt[OPT_GEOMETRY_GROUP].size = 0;
7152   s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7153 
7154   /* top-left x */
7155   s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
7156   s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
7157   s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
7158   s->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
7159   s->opt[OPT_TL_X].unit = SANE_UNIT_MM;
7160   s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
7161   s->opt[OPT_TL_X].constraint.range = &dev->x_range;
7162   s->val[OPT_TL_X].w = 0;
7163 
7164   /* top-left y */
7165   s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
7166   s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
7167   s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
7168   s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
7169   s->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
7170   s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
7171   s->opt[OPT_TL_Y].constraint.range = &dev->y_range;
7172   s->val[OPT_TL_Y].w = 0;
7173 
7174   /* bottom-right x */
7175   s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
7176   s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
7177   s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
7178   s->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
7179   s->opt[OPT_BR_X].unit = SANE_UNIT_MM;
7180   s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
7181   s->opt[OPT_BR_X].constraint.range = &dev->x_range;
7182   s->val[OPT_BR_X].w = dev->x_range.max;
7183 
7184   /* bottom-right y */
7185   s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
7186   s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
7187   s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
7188   s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
7189   s->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
7190   s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
7191   s->opt[OPT_BR_Y].constraint.range = &dev->y_range;
7192   s->val[OPT_BR_Y].w = dev->y_range.max;
7193 
7194   /* overscan top */
7195   s->opt[OPT_OVERSCAN_TOP].name = "overscan-top";
7196   s->opt[OPT_OVERSCAN_TOP].title = SANE_TITLE_OVERSCAN_TOP;
7197   s->opt[OPT_OVERSCAN_TOP].desc = SANE_DESC_OVERSCAN_TOP;
7198   s->opt[OPT_OVERSCAN_TOP].type = SANE_TYPE_FIXED;
7199   s->opt[OPT_OVERSCAN_TOP].unit = SANE_UNIT_MM;
7200   s->opt[OPT_OVERSCAN_TOP].constraint_type = SANE_CONSTRAINT_RANGE;
7201   s->opt[OPT_OVERSCAN_TOP].constraint.range = &overscan_range;
7202   s->val[OPT_OVERSCAN_TOP].w = SANE_FIX(0);
7203 
7204   /* overscan bottom */
7205   s->opt[OPT_OVERSCAN_BOTTOM].name = "overscan-bottom";
7206   s->opt[OPT_OVERSCAN_BOTTOM].title = SANE_TITLE_OVERSCAN_BOTTOM;
7207   s->opt[OPT_OVERSCAN_BOTTOM].desc = SANE_DESC_OVERSCAN_BOTTOM;
7208   s->opt[OPT_OVERSCAN_BOTTOM].type = SANE_TYPE_FIXED;
7209   s->opt[OPT_OVERSCAN_BOTTOM].unit = SANE_UNIT_MM;
7210   s->opt[OPT_OVERSCAN_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE;
7211   s->opt[OPT_OVERSCAN_BOTTOM].constraint.range = &overscan_range;
7212   s->val[OPT_OVERSCAN_BOTTOM].w = SANE_FIX(0);
7213 
7214   if (!dev->inquiry_tune_scan_length)
7215     s->opt[OPT_OVERSCAN_TOP].cap |= SANE_CAP_INACTIVE;
7216   if (!dev->inquiry_tune_scan_length)
7217     s->opt[OPT_OVERSCAN_BOTTOM].cap |= SANE_CAP_INACTIVE;
7218 
7219   /* background raster */
7220   s->opt[OPT_BACKGROUND].name = "background-lines";
7221   s->opt[OPT_BACKGROUND].title = SANE_TITLE_BACKGROUND_LINES;
7222   s->opt[OPT_BACKGROUND].desc = SANE_DESC_BACKGROUND_LINES;
7223   s->opt[OPT_BACKGROUND].type = SANE_TYPE_INT;
7224   s->opt[OPT_BACKGROUND].unit = SANE_UNIT_PIXEL;
7225   s->opt[OPT_BACKGROUND].constraint_type = SANE_CONSTRAINT_RANGE;
7226   s->opt[OPT_BACKGROUND].constraint.range = &background_range;
7227   s->val[OPT_BACKGROUND].w = 0;
7228 
7229   if (!dev->inquiry_background_raster) {
7230     s->opt[OPT_BACKGROUND].cap |= SANE_CAP_INACTIVE;
7231   }
7232 
7233   /* "Enhancement" group: */
7234   s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT;
7235   s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
7236   s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
7237   s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
7238   s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7239 
7240   /* brightness */
7241   s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
7242   s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
7243   s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
7244   s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
7245   if (disable_gamma_table)
7246     s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
7247   s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
7248   s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
7249   s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range;
7250   s->val[OPT_BRIGHTNESS].w = SANE_FIX(0);
7251 
7252   /* contrast */
7253   s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
7254   s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
7255   s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
7256   s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED;
7257   if (disable_gamma_table)
7258     s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
7259   s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
7260   s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
7261   s->opt[OPT_CONTRAST].constraint.range = &percentage_range;
7262   s->val[OPT_CONTRAST].w = SANE_FIX(0);
7263 
7264   /* Quality Scan */
7265   s->opt[OPT_QSCAN].name   = "quality-scan";
7266   s->opt[OPT_QSCAN].title  = SANE_TITLE_QUALITY_SCAN;
7267   s->opt[OPT_QSCAN].desc   = SANE_DESC_QUALITY_SCAN;
7268   s->opt[OPT_QSCAN].type   = SANE_TYPE_BOOL;
7269   s->opt[OPT_QSCAN].unit   = SANE_UNIT_NONE;
7270   s->val[OPT_QSCAN].w      = SANE_TRUE;
7271   if (dev->hw->feature_type & AV_NO_QSCAN_MODE)
7272     s->opt[OPT_QSCAN].cap |= SANE_CAP_INACTIVE;
7273 
7274   /* Quality Calibration */
7275   s->opt[OPT_QCALIB].name  = SANE_NAME_QUALITY_CAL;
7276   s->opt[OPT_QCALIB].title = SANE_TITLE_QUALITY_CAL;
7277   s->opt[OPT_QCALIB].desc  = SANE_DESC_QUALITY_CAL;
7278   s->opt[OPT_QCALIB].type  = SANE_TYPE_BOOL;
7279   s->opt[OPT_QCALIB].unit  = SANE_UNIT_NONE;
7280   s->val[OPT_QCALIB].w     = SANE_TRUE;
7281   if (dev->hw->feature_type & AV_NO_QCALIB_MODE)
7282     s->opt[OPT_QCALIB].cap |= SANE_CAP_INACTIVE;
7283 
7284   /* gray scale gamma vector */
7285   s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR;
7286   s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR;
7287   s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR;
7288   s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT;
7289   s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE;
7290   s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE;
7291   s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word);
7292   s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE;
7293   s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range;
7294   s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0];
7295 
7296   /* red gamma vector */
7297   s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
7298   s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
7299   s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
7300   s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
7301   s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
7302   s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
7303   s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word);
7304   s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
7305   s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range;
7306   s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0];
7307 
7308   /* green gamma vector */
7309   s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
7310   s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
7311   s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
7312   s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
7313   s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
7314   s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
7315   s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word);
7316   s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
7317   s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range;
7318   s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0];
7319 
7320   /* blue gamma vector */
7321   s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
7322   s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
7323   s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
7324   s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
7325   s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
7326   s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
7327   s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word);
7328   s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
7329   s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range;
7330   s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0];
7331 
7332   if (!disable_gamma_table)
7333   {
7334     if (color_mode_is_color (s->c_mode)) {
7335       s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
7336       s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
7337       s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
7338     }
7339     else {
7340       s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
7341     }
7342   }
7343 
7344   /* exposure */
7345   s->opt[OPT_EXPOSURE].name = "exposure";
7346   s->opt[OPT_EXPOSURE].title = SANE_TITLE_MANUAL_EXPOSURE;
7347   s->opt[OPT_EXPOSURE].desc = SANE_DESC_MANUAL_EXPOSURE;
7348   s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT;
7349   s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT;
7350   s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
7351   s->opt[OPT_EXPOSURE].constraint.range = &exposure_range;
7352   s->val[OPT_EXPOSURE].w = 100;
7353 
7354   if (!dev->inquiry_exposure_control) {
7355     s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE;
7356   }
7357 
7358   /* Multi sample */
7359   s->opt[OPT_MULTISAMPLE].name  = "multi-sample";
7360   s->opt[OPT_MULTISAMPLE].title = SANE_TITLE_MULTI_SAMPLE;
7361   s->opt[OPT_MULTISAMPLE].desc  = SANE_DESC_MULTI_SAMPLE;
7362   s->opt[OPT_MULTISAMPLE].type  = SANE_TYPE_BOOL;
7363   s->opt[OPT_MULTISAMPLE].unit  = SANE_UNIT_NONE;
7364   s->val[OPT_MULTISAMPLE].w     = SANE_FALSE;
7365 
7366   /* TODO: No idea how to detect, assume exposure control devices are
7367      new enough to support this, for now. -ReneR */
7368   if (!dev->inquiry_exposure_control) {
7369     s->opt[OPT_MULTISAMPLE].cap |= SANE_CAP_INACTIVE;
7370   }
7371 
7372   /* Infra-red */
7373   s->opt[OPT_IR].name  = SANE_NAME_INFRARED;
7374   s->opt[OPT_IR].title = SANE_TITLE_INFRARED;
7375   s->opt[OPT_IR].desc  = SANE_DESC_INFRARED;
7376   s->opt[OPT_IR].type  = SANE_TYPE_BOOL;
7377   s->opt[OPT_IR].unit  = SANE_UNIT_NONE;
7378   s->val[OPT_IR].w     = SANE_FALSE;
7379 
7380   /* TODO: No idea how to detect, assume exposure control devices are
7381      new enough to support this, for now. -ReneR */
7382   if (!dev->inquiry_exposure_control) {
7383     s->opt[OPT_IR].cap |= SANE_CAP_INACTIVE;
7384   }
7385 
7386   /* "MISC" group: */
7387   s->opt[OPT_MISC_GROUP].title = SANE_TITLE_MISC_GROUP;
7388   s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP;
7389   s->opt[OPT_MISC_GROUP].cap = 0;
7390   s->opt[OPT_MISC_GROUP].size = 0;
7391   s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7392 
7393   /* film holder control */
7394   s->opt[OPT_FRAME].name = SANE_NAME_FRAME;
7395   s->opt[OPT_FRAME].title = SANE_TITLE_FRAME;
7396   s->opt[OPT_FRAME].desc = SANE_DESC_FRAME;
7397   s->opt[OPT_FRAME].type = SANE_TYPE_INT;
7398   s->opt[OPT_FRAME].unit = SANE_UNIT_NONE;
7399   s->opt[OPT_FRAME].constraint_type = SANE_CONSTRAINT_RANGE;
7400   s->opt[OPT_FRAME].constraint.range = &dev->frame_range;
7401   s->val[OPT_FRAME].w = dev->current_frame;
7402   if (dev->scanner_type != AV_FILM)
7403     s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE;
7404 
7405   /* power save time */
7406   s->opt[OPT_POWER_SAVE_TIME].name = "power-save-time";
7407   s->opt[OPT_POWER_SAVE_TIME].title = SANE_TITLE_POWER_SAVE_TIME;
7408   s->opt[OPT_POWER_SAVE_TIME].desc = SANE_DESC_POWER_SAVE_TIME;
7409   s->opt[OPT_POWER_SAVE_TIME].type = SANE_TYPE_INT;
7410   s->opt[OPT_POWER_SAVE_TIME].unit = SANE_UNIT_NONE;
7411   s->opt[OPT_POWER_SAVE_TIME].constraint_type = SANE_CONSTRAINT_NONE;
7412   s->val[OPT_POWER_SAVE_TIME].w = 0;
7413   if (!dev->inquiry_power_save_time)
7414     s->opt[OPT_POWER_SAVE_TIME].cap |= SANE_CAP_INACTIVE;
7415 
7416   /* message, like options set on the scanner, LED no. & co */
7417   s->opt[OPT_MESSAGE].name = "message";
7418   s->opt[OPT_MESSAGE].title = SANE_TITLE_OPTIONS_MSG;
7419   s->opt[OPT_MESSAGE].desc = SANE_DESC_OPTIONS_MSG;
7420   s->opt[OPT_MESSAGE].type = SANE_TYPE_STRING;
7421   s->opt[OPT_MESSAGE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7422   s->opt[OPT_MESSAGE].size = 129;
7423   s->opt[OPT_MESSAGE].constraint_type = SANE_CONSTRAINT_NONE;
7424   s->val[OPT_MESSAGE].s = malloc((size_t) s->opt[OPT_MESSAGE].size);
7425   s->val[OPT_MESSAGE].s[0] = 0;
7426 
7427   /* NVRAM */
7428   s->opt[OPT_NVRAM].name = "nvram-values";
7429   s->opt[OPT_NVRAM].title = SANE_TITLE_NVRAM;
7430   s->opt[OPT_NVRAM].desc = SANE_DESC_NVRAM;
7431   s->opt[OPT_NVRAM].type = SANE_TYPE_STRING;
7432   s->opt[OPT_NVRAM].unit = SANE_UNIT_NONE;
7433   s->opt[OPT_NVRAM].size = 1024;
7434   s->opt[OPT_NVRAM].constraint_type = SANE_CONSTRAINT_NONE;
7435   s->val[OPT_NVRAM].s = malloc((size_t) s->opt[OPT_NVRAM].size);
7436   s->val[OPT_NVRAM].s[0] = 0;
7437   s->opt[OPT_NVRAM].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7438   if (!dev->inquiry_nvram_read)
7439     s->opt[OPT_NVRAM].cap |= SANE_CAP_INACTIVE;
7440 
7441   /* paper_length */
7442   s->opt[OPT_PAPERLEN].name  = "paper-length";
7443   s->opt[OPT_PAPERLEN].title = SANE_TITLE_PAPER_LENGTH;
7444   s->opt[OPT_PAPERLEN].desc  = SANE_DESC_PAPER_LENGTH;
7445   s->opt[OPT_PAPERLEN].type  = SANE_TYPE_BOOL;
7446   s->opt[OPT_PAPERLEN].unit  = SANE_UNIT_NONE;
7447   s->opt[OPT_PAPERLEN].size = sizeof(SANE_Word);
7448   s->opt[OPT_PAPERLEN].constraint_type = SANE_CONSTRAINT_NONE;
7449   s->val[OPT_PAPERLEN].w     = SANE_FALSE;
7450   s->opt[OPT_PAPERLEN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7451   if (!dev->inquiry_paper_length)
7452     s->opt[OPT_PAPERLEN].cap |= SANE_CAP_INACTIVE;
7453 
7454   /* ADF page flipping */
7455   s->opt[OPT_ADF_FLIP].name = "flip-page";
7456   s->opt[OPT_ADF_FLIP].title = SANE_TITLE_FLIP_PAGE;
7457   s->opt[OPT_ADF_FLIP].desc = SANE_DESC_FLIP_PAGE;
7458   s->opt[OPT_ADF_FLIP].type = SANE_TYPE_BOOL;
7459   s->opt[OPT_ADF_FLIP].unit = SANE_UNIT_NONE;
7460   s->opt[OPT_ADF_FLIP].size = sizeof(SANE_Word);
7461   s->opt[OPT_ADF_FLIP].constraint_type = SANE_CONSTRAINT_NONE;
7462   s->val[OPT_ADF_FLIP].w = SANE_TRUE;
7463   s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
7464   if (!((s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && (s->source_mode == AV_ADF_DUPLEX)))
7465     s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
7466 
7467   /* "Options" group: */
7468   s->opt[OPT_OPTIONS_GROUP].title = SANE_TITLE_INSTALLED_OPTS_GROUP;
7469   s->opt[OPT_OPTIONS_GROUP].type = SANE_TYPE_GROUP;
7470   s->opt[OPT_OPTIONS_GROUP].cap = 0;
7471   s->opt[OPT_OPTIONS_GROUP].size = 0;
7472   s->opt[OPT_OPTIONS_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
7473 
7474   /* ADF Installed */
7475   s->opt[OPT_OPTION_ADF].name = "adf-installed";
7476   s->opt[OPT_OPTION_ADF].title = SANE_TITLE_ADF_INSTALLED;
7477   s->opt[OPT_OPTION_ADF].desc = SANE_DESC_ADF_INSTALLED;
7478   s->opt[OPT_OPTION_ADF].type = SANE_TYPE_BOOL;
7479   s->opt[OPT_OPTION_ADF].unit = SANE_UNIT_NONE;
7480   s->opt[OPT_OPTION_ADF].size = sizeof(SANE_Word);
7481   s->opt[OPT_OPTION_ADF].constraint_type = SANE_CONSTRAINT_NONE;
7482   s->val[OPT_OPTION_ADF].w = dev->inquiry_adf_present;
7483   s->opt[OPT_OPTION_ADF].cap =  SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7484 
7485   /* Lightbox Installed */
7486   s->opt[OPT_OPTION_LIGHTBOX].name = "lightbox-installed";
7487   s->opt[OPT_OPTION_LIGHTBOX].title = SANE_TITLE_LIGHTBOX_INSTALLED;
7488   s->opt[OPT_OPTION_LIGHTBOX].desc = SANE_DESC_LIGHTBOX_INSTALLED;
7489   s->opt[OPT_OPTION_LIGHTBOX].type = SANE_TYPE_BOOL;
7490   s->opt[OPT_OPTION_LIGHTBOX].unit = SANE_UNIT_NONE;
7491   s->opt[OPT_OPTION_LIGHTBOX].size = sizeof(SANE_Word);
7492   s->opt[OPT_OPTION_LIGHTBOX].constraint_type = SANE_CONSTRAINT_NONE;
7493   s->val[OPT_OPTION_LIGHTBOX].w = dev->inquiry_light_box_present;
7494   s->opt[OPT_OPTION_LIGHTBOX].cap =  SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
7495 
7496   return SANE_STATUS_GOOD;
7497 }
7498 
7499 /* This function is executed as a child process. The reason this is
7500    executed as a subprocess is because some (most?) generic SCSI
7501    interfaces block a SCSI request until it has completed. With a
7502    subprocess, we can let it block waiting for the request to finish
7503    while the main process can go about to do more important things
7504    (such as recognizing when the user presses a cancel button).
7505 
7506    WARNING: Since this is executed as a subprocess, it's NOT possible
7507    to update any of the variables in the main process (in particular
7508    the scanner state cannot be updated).  */
7509 
7510 static int
reader_process(void * data)7511 reader_process (void *data)
7512 {
7513   struct Avision_Scanner *s = (struct Avision_Scanner *) data;
7514   int fd = s->write_fds;
7515 
7516   Avision_Device* dev = s->hw;
7517 
7518   SANE_Status status;
7519   SANE_Status exit_status = SANE_STATUS_GOOD;
7520   sigset_t sigterm_set;
7521   sigset_t ignore_set;
7522   struct SIGACTION act;
7523 
7524   FILE* fp;
7525   FILE* fp_fd = 0; /* for ADF bottom offset truncating */
7526   FILE* rear_fp = 0; /* used to store the deinterlaced rear data */
7527   FILE* raw_fp = 0; /* used to write the RAW image data for debugging */
7528 
7529   /* the complex params */
7530   unsigned int lines_per_stripe;
7531   unsigned int lines_per_output;
7532   unsigned int max_bytes_per_read;
7533 
7534   SANE_Bool gray_mode;
7535 
7536   /* the simple params for the data reader */
7537   int hw_line = 0;
7538   int line = 0;
7539 
7540   unsigned int stripe_size;
7541   unsigned int stripe_fill;
7542   unsigned int out_size;
7543 
7544   size_t total_size;
7545   size_t processed_bytes;
7546 
7547   enum {
7548     NONE,   /* do not de-interlace at all */
7549     STRIPE, /* every 2nd stripe */
7550     HALF,   /* the 2nd half */
7551     LINE    /* every 2nd line */
7552   } deinterlace = NONE;
7553 
7554   /* the fat strip we currently puzzle together to perform software-colorpack
7555      and more */
7556   uint8_t* stripe_data;
7557   /* the corrected output data */
7558   uint8_t* out_data;
7559   /* interpolation output data, one line */
7560   uint8_t* ip_history = 0;
7561   uint8_t* ip_data = 0;
7562 
7563   DBG (3, "reader_process:\n");
7564 
7565   if (sanei_thread_is_forked()) {
7566     close (s->read_fds);
7567     s->read_fds = -1;
7568 
7569     sigfillset (&ignore_set);
7570     sigdelset (&ignore_set, SIGTERM);
7571 #if defined (__APPLE__) && defined (__MACH__)
7572     sigdelset (&ignore_set, SIGUSR2);
7573 #endif
7574     sigprocmask (SIG_SETMASK, &ignore_set, 0);
7575 
7576     memset (&act, 0, sizeof (act));
7577     sigaction (SIGTERM, &act, 0);
7578 
7579     sigemptyset (&sigterm_set);
7580     sigaddset (&sigterm_set, SIGTERM);
7581   }
7582 #ifdef USE_PTHREAD
7583   else {
7584     int old;
7585     pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
7586     pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
7587   }
7588 #endif
7589 
7590   gray_mode = color_mode_is_shaded (s->c_mode);
7591 
7592   if (s->avdimen.interlaced_duplex) {
7593     deinterlace = STRIPE;
7594 
7595     if ( (dev->hw->feature_type & AV_NON_INTERLACED_DUPLEX_300) &&
7596 	 (s->avdimen.hw_xres <= 300 && s->avdimen.hw_yres <= 300) )
7597       deinterlace = HALF;
7598     if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED)
7599       deinterlace = LINE;
7600 
7601     if (dev->scanner_type == AV_FILM)
7602       deinterlace = LINE;
7603   }
7604 
7605   fp = fdopen (fd, "w");
7606   if (!fp)
7607     return SANE_STATUS_NO_MEM;
7608 
7609   if (dev->adf_offset_compensation) {
7610     char duplex_offtmp_fname [] = "/tmp/avision-offtmp-XXXXXX";
7611 
7612     int fd = mkstemp(duplex_offtmp_fname);
7613     if (fd == -1) {
7614       DBG (1, "reader_process: failed to generate temporary fname for ADF offset compensation temp file\n");
7615       return SANE_STATUS_NO_MEM;
7616     }
7617     DBG (1, "reader_process: temporary fname for ADF offset compensation temp file: %s\n",
7618          duplex_offtmp_fname);
7619 
7620     if (unlink(duplex_offtmp_fname) == -1) {
7621       DBG(1, "reader_process: failed to delete temporary file prior to use: %s\n", duplex_offtmp_fname);
7622       // continue though.
7623     }
7624 
7625     DBG (3, "reader_process: redirecting output data to temp file for ADF offset compensation.\n");
7626     fp_fd = fp;
7627     fp = fdopen (fd, "w+");
7628     if (!fp) {
7629       fclose(fp_fd);
7630       close(fd);
7631       return SANE_STATUS_NO_MEM;
7632     }
7633   }
7634 
7635   /* start scan ? */
7636   if ((deinterlace == NONE && !((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->duplex_rear_valid)) ||
7637       (deinterlace != NONE && !s->duplex_rear_valid))
7638     {
7639       /* reserve unit - in the past we did this in open - but the
7640 	 windows driver does reserves for each scan and some ADF
7641 	 devices need a release for each sheet anyway ... */
7642       status = reserve_unit (s);
7643       if (status != SANE_STATUS_GOOD) {
7644 	DBG (1, "reader_process: reserve_unit failed: %s\n",
7645 	     sane_strstatus (status));
7646 	return status;
7647       }
7648 
7649       if (dev->hw->feature_type & AV_NO_START_SCAN) {
7650 	DBG (1, "reader_process: start_scan skipped due to device-list!\n");
7651       }
7652       else {
7653 	status = start_scan (s);
7654 	if (status != SANE_STATUS_GOOD) {
7655 	  DBG (1, "reader_process: start_scan failed: %s\n",
7656 	       sane_strstatus (status));
7657 	  return status;
7658 	}
7659       }
7660 
7661       if (dev->hw->feature_type & AV_ACCEL_TABLE)
7662      /*  (s->hw->inquiry_asic_type == AV_ASIC_C6) */ {
7663 	status = send_acceleration_table (s);
7664 	if (status != SANE_STATUS_GOOD) {
7665 	  DBG (1, "reader_process: send_acceleration_table failed: %s\n",
7666 	       sane_strstatus (status));
7667 	  return status;
7668 	}
7669       }
7670     }
7671 
7672   /* setup file i/o for deinterlacing scans or if we are the back page with a flipping duplexer */
7673   if (deinterlace != NONE ||
7674      (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2)))
7675     {
7676       if (!s->duplex_rear_valid) { /* create new file for writing */
7677 	DBG (3, "reader_process: opening duplex rear file for writing.\n");
7678 	rear_fp = fopen (s->duplex_rear_fname, "w");
7679       }
7680       else { /* open saved rear data */
7681 	DBG (3, "reader_process: opening duplex rear file for reading.\n");
7682 	rear_fp = fopen (s->duplex_rear_fname, "r");
7683       }
7684       if (! rear_fp) {
7685 	fclose (fp);
7686 	fclose (fp_fd);
7687 	return SANE_STATUS_IO_ERROR;
7688       }
7689     }
7690 
7691   /* it takes quite a few lines to saturate the (USB) bus */
7692   lines_per_stripe = (unsigned int) dev->read_stripe_size;
7693   if (s->avdimen.line_difference)
7694     lines_per_stripe += (2 * (unsigned int) s->avdimen.line_difference);
7695 
7696   stripe_size = (unsigned int) s->avdimen.hw_bytes_per_line * lines_per_stripe;
7697   lines_per_output = lines_per_stripe - 2 * (unsigned int) s->avdimen.line_difference;
7698 
7699   if (s->av_con.connection_type == AV_SCSI)
7700     /* maybe better not /2 ... */
7701     max_bytes_per_read = (unsigned int) dev->scsi_buffer_size / 2;
7702   else
7703     /* vast buffer size to saturate the bus */
7704     max_bytes_per_read = 0x100000;
7705 
7706   out_size = (unsigned int) s->avdimen.hw_bytes_per_line * lines_per_output;
7707 
7708   DBG (3, "dev->scsi_buffer_size / 2: %d\n",
7709        dev->scsi_buffer_size / 2);
7710 
7711   DBG (3, "bytes_per_line: %d, pixels_per_line: %d\n",
7712        s->avdimen.hw_bytes_per_line, s->avdimen.hw_pixels_per_line);
7713 
7714   DBG (3, "lines_per_stripe: %d, lines_per_output: %d\n",
7715        lines_per_stripe, lines_per_output);
7716 
7717   DBG (3, "max_bytes_per_read: %d, stripe_size: %d, out_size: %d\n",
7718        max_bytes_per_read, stripe_size, out_size);
7719 
7720   stripe_data = malloc (stripe_size);
7721 
7722   /* for software scaling we need an additional interpolation line buffer */
7723   if (s->avdimen.hw_xres != s->avdimen.xres ||
7724       s->avdimen.hw_yres != s->avdimen.yres)
7725   {
7726     /* layout out_data so that the interpolation history is exactly in front */
7727     ip_history = malloc ((size_t) s->avdimen.hw_bytes_per_line + out_size);
7728     out_data = ip_history + s->avdimen.hw_bytes_per_line;
7729 
7730     ip_data = malloc ((size_t) s->params.bytes_per_line);
7731   }
7732   else {
7733     out_data = malloc (out_size);
7734   }
7735 
7736   /* calculate params for the reading loop */
7737   total_size = (size_t) s->avdimen.hw_bytes_per_line *
7738                ((size_t) s->avdimen.hw_lines + 2 * (size_t) s->avdimen.line_difference);
7739 
7740   if (deinterlace != NONE && !s->duplex_rear_valid)
7741     total_size *= 2;
7742   DBG (3, "reader_process: total_size: %lu\n", (u_long) total_size);
7743 
7744   /* write a RAW PNM file for debugging -ReneR */
7745   if (0 /* DEBUG */ &&
7746       (deinterlace == NONE || (deinterlace != NONE && !s->duplex_rear_valid)) )
7747     {
7748       raw_fp = fopen ("/tmp/sane-avision.raw", "w");
7749       write_pnm_header (fp, s->c_mode, s->params.depth,
7750 			s->avdimen.hw_pixels_per_line, (int) (total_size / (size_t) s->avdimen.hw_bytes_per_line));
7751     }
7752 
7753   processed_bytes = 0;
7754   stripe_fill = 0;
7755 
7756   /* First, dump background raster, bypassing all the other processing. */
7757   if (dev->inquiry_background_raster && s->val[OPT_BACKGROUND].w)
7758     {
7759       uint8_t* background = s->background_raster;
7760       if (s->duplex_rear_valid)
7761 	background += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w;
7762 
7763       DBG (5, "reader_process: dumping background raster\n");
7764       fwrite (background, (size_t) s->params.bytes_per_line, (size_t) s->val[OPT_BACKGROUND].w, fp);
7765     }
7766 
7767   /* Data read; loop until all data has been processed.  Might exit
7768      before all lines are transferred for ADF paper end. */
7769   while (exit_status == SANE_STATUS_GOOD && processed_bytes < total_size)
7770     {
7771       unsigned int useful_bytes;
7772 
7773       DBG (5, "reader_process: stripe filled: %d\n", stripe_fill);
7774 
7775       /* fill the stripe buffer with real data */
7776       while (!s->duplex_rear_valid &&
7777 	     processed_bytes < total_size && stripe_fill < stripe_size &&
7778              exit_status  == SANE_STATUS_GOOD)
7779 	{
7780 	  size_t this_read = stripe_size - stripe_fill;
7781 
7782 	  /* Limit reads to max_bytes_per_read and global data
7783 	     boundaries. Rounded to the next lower multiple of
7784 	     byte_per_lines, otherwise some scanners freeze. */
7785 	  if (this_read > max_bytes_per_read)
7786 	    this_read = (max_bytes_per_read -
7787 			 max_bytes_per_read % (unsigned int) s->avdimen.hw_bytes_per_line);
7788 
7789 	  if (processed_bytes + this_read > total_size)
7790 	    this_read = total_size - processed_bytes;
7791 
7792           read_constrains(s, this_read);
7793 
7794 	  DBG (5, "reader_process: processed_bytes: %lu, total_size: %lu\n",
7795 	       (u_long) processed_bytes, (u_long) total_size);
7796 	  DBG (5, "reader_process: this_read: %lu\n", (u_long) this_read);
7797 
7798 	  if (sanei_thread_is_forked())
7799 	    sigprocmask (SIG_BLOCK, &sigterm_set, 0);
7800 #ifdef USE_PTHREAD
7801 	  else
7802 	    {
7803 	      int old;
7804 	      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
7805 	    }
7806 #endif
7807 
7808 	  status = read_data (s, stripe_data + stripe_fill, &this_read);
7809 
7810 	  if (sanei_thread_is_forked())
7811 	    sigprocmask (SIG_UNBLOCK, &sigterm_set, 0);
7812 #ifdef USE_PTHREAD
7813 	  else
7814 	    {
7815 	      int old;
7816 	      pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &old);
7817 	    }
7818 #endif
7819 
7820 	  /* only EOF on the second stripe, as otherwise the rear page
7821 	     is shorter */
7822 	  if (status == SANE_STATUS_EOF && deinterlace == STRIPE) {
7823 	    if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980) {
7824 	      this_read = 0;
7825 	    } else {
7826 	      static int already_eof = 0;
7827 	      if (!already_eof) {
7828 		DBG (5, "reader_process: first EOF on stripe interlace: hiding.\n");
7829 		status = SANE_STATUS_GOOD;
7830 		already_eof = 1;
7831 	      }
7832 	    }
7833 	  }
7834 
7835 	  /* write RAW data to file for debugging */
7836 	  if (raw_fp && this_read > 0)
7837 	    fwrite (stripe_data + stripe_fill, this_read, 1, raw_fp);
7838 
7839 	  if (status == SANE_STATUS_EOF || this_read == 0) {
7840 	    DBG (1, "reader_process: read_data failed due to EOF\n");
7841 	    exit_status = SANE_STATUS_EOF;
7842 	  }
7843 
7844 	  if (status != SANE_STATUS_GOOD) {
7845 	    DBG (1, "reader_process: read_data failed with status: %d\n",
7846 		 status);
7847 	    exit_status = status;
7848 	  }
7849 
7850 	  stripe_fill += (unsigned int) this_read;
7851 	  processed_bytes += this_read;
7852 	}
7853 
7854       /* fill the stripe buffer with stored, virtual data */
7855       if (s->duplex_rear_valid)
7856 	{
7857 	  size_t this_read = stripe_size - stripe_fill;
7858 	  size_t got;
7859 
7860 	  /* limit reads to max_read and global data boundaries */
7861 	  if (this_read > max_bytes_per_read)
7862 	    this_read = max_bytes_per_read;
7863 
7864 	  if (processed_bytes + this_read > total_size)
7865 	    this_read = total_size - processed_bytes;
7866 
7867 	  DBG (5, "reader_process: virtual processed_bytes: %lu, total_size: %lu\n",
7868 	       (u_long) processed_bytes, (u_long) total_size);
7869 	  DBG (5, "reader_process: virtual this_read: %lu\n", (u_long) this_read);
7870 
7871 	  got = fread (stripe_data + stripe_fill, 1, this_read, rear_fp);
7872 	  stripe_fill += (unsigned int) got;
7873 	  processed_bytes += got;
7874 	  if (got != this_read)
7875 	    exit_status = SANE_STATUS_EOF;
7876 	}
7877 
7878       DBG (5, "reader_process: stripe filled: %d\n", stripe_fill);
7879 
7880       useful_bytes = stripe_fill;
7881 
7882       if (color_mode_is_color (s->c_mode))
7883 	useful_bytes -= (unsigned int) (2 * s->avdimen.line_difference * s->avdimen.hw_bytes_per_line);
7884 
7885       DBG (3, "reader_process: useful_bytes %i\n", useful_bytes);
7886 
7887       /* Deinterlace, save the rear stripes. For some scanners (AV220)
7888 	 that is every 2nd stripe, the 2nd half of the transferred
7889 	 data ((AV83xx), or every 2nd line (AV122)). */
7890       if (deinterlace != NONE && !s->duplex_rear_valid)
7891 	{
7892 	  /* for all lines we have in the buffer: */
7893 	  unsigned int absline = (unsigned int) ((processed_bytes - stripe_fill) / (size_t) s->avdimen.hw_bytes_per_line);
7894 	  unsigned int abslines = absline + useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
7895 	  uint8_t* ptr = stripe_data;
7896 	  for ( ; absline < abslines; ++absline)
7897 	    {
7898 	      DBG (9, "reader_process: deinterlacing line %d\n", absline);
7899 	      /* interlaced? save the back data to the rear buffer */
7900 	      if ( (deinterlace == STRIPE && absline % (lines_per_stripe*2) >= lines_per_stripe) ||
7901 		   (deinterlace == HALF   && absline >= total_size / (size_t) s->avdimen.hw_bytes_per_line / 2) ||
7902 		   (deinterlace == LINE   && (absline & 0x1)) ) /* last bit equals % 2 */
7903 		{
7904 		  DBG (9, "reader_process: saving rear line %d to temporary file.\n", absline);
7905 		  fwrite (ptr, (size_t) s->avdimen.hw_bytes_per_line, 1, rear_fp);
7906 		  if (deinterlace == LINE)
7907 		    memmove (ptr, ptr+s->avdimen.hw_bytes_per_line,
7908 			     (size_t) (stripe_data + stripe_fill - ptr - s->avdimen.hw_bytes_per_line));
7909 		  else
7910 		    ptr += s->avdimen.hw_bytes_per_line;
7911 		  useful_bytes -= (unsigned int) s->avdimen.hw_bytes_per_line;
7912 		  stripe_fill -= (unsigned int) s->avdimen.hw_bytes_per_line;
7913 		}
7914 	      else
7915 		ptr += s->avdimen.hw_bytes_per_line;
7916  	    }
7917 	  DBG (9, "reader_process: after deinterlacing: useful_bytes: %d, stripe_fill: %d\n",
7918 	       useful_bytes, stripe_fill);
7919 	}
7920       if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && !s->duplex_rear_valid) {
7921         /* Here we flip the image by writing the lines from the end of the file to the beginning. */
7922 	unsigned int absline = (unsigned int) ((processed_bytes - stripe_fill) / (size_t) s->avdimen.hw_bytes_per_line);
7923 	unsigned int abslines = absline + useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
7924 	uint8_t* ptr = stripe_data;
7925 	for ( ; absline < abslines; ++absline) {
7926           fseek (rear_fp, ((0 - s->params.lines) - (SANE_Int) absline - 2) * s->avdimen.hw_bytes_per_line, SEEK_SET);
7927           fwrite (ptr, (size_t) s->avdimen.hw_bytes_per_line, 1, rear_fp);
7928           useful_bytes -= (unsigned int) s->avdimen.hw_bytes_per_line;
7929           stripe_fill -= (unsigned int) s->avdimen.hw_bytes_per_line;
7930           ptr += s->avdimen.hw_bytes_per_line;
7931         }
7932 	DBG (9, "reader_process: after page flip: useful_bytes: %d, stripe_fill: %d\n",
7933 	       useful_bytes, stripe_fill);
7934       } else {
7935 
7936       /*
7937        * Perform needed data conversions (packing, ...) and/or copy the
7938        * image data.
7939        */
7940 
7941       if (s->c_mode != AV_TRUECOLOR && s->c_mode != AV_TRUECOLOR16)
7942 	/* simple copy */
7943 	{
7944 	  memcpy (out_data, stripe_data, useful_bytes);
7945 	}
7946       else /* AV_TRUECOLOR* */
7947 	{
7948 	  /* WARNING: DO NOT MODIFY MY (HOPEFULLY WELL) OPTIMIZED
7949 	     ALGORITHMS BELOW, WITHOUT UNDERSTANDING THEM FULLY ! */
7950 	  if (s->avdimen.line_difference > 0) /* color-pack */
7951 	    {
7952 	      /* TODO: add 16bit per sample code? */
7953 	      unsigned int i;
7954 	      int c_offset = s->avdimen.line_difference * s->avdimen.hw_bytes_per_line;
7955 
7956 	      uint8_t* r_ptr = stripe_data;
7957 	      uint8_t* g_ptr = stripe_data + c_offset + 1;
7958 	      uint8_t* b_ptr = stripe_data + 2 * c_offset + 2;
7959 
7960 	      for (i = 0; i < useful_bytes;) {
7961 		out_data [i++] = *r_ptr; r_ptr += 3;
7962 		out_data [i++] = *g_ptr; g_ptr += 3;
7963 		out_data [i++] = *b_ptr; b_ptr += 3;
7964 	      }
7965 	    } /* end color pack */
7966 	  else if (dev->inquiry_needs_line_pack) /* line-pack */
7967 	    {
7968 	      /* TODO: add 16bit per sample code? */
7969 	      unsigned int i = 0, l, p;
7970 	      const unsigned int lines = useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
7971 
7972 	      for (l = 0; l < lines; ++l)
7973 		{
7974 		  uint8_t* r_ptr = stripe_data + ((unsigned int) s->avdimen.hw_bytes_per_line * l);
7975 		  uint8_t* g_ptr = r_ptr + s->avdimen.hw_pixels_per_line;
7976 		  uint8_t* b_ptr = g_ptr + s->avdimen.hw_pixels_per_line;
7977 
7978 		  for (p = 0; p < (unsigned int) s->avdimen.hw_pixels_per_line; ++p) {
7979 		    out_data [i++] = *(r_ptr++);
7980 		    out_data [i++] = *(g_ptr++);
7981 		    out_data [i++] = *(b_ptr++);
7982 		  }
7983 		}
7984 	    } /* end line pack */
7985 	  else /* else no packing was required -> simple copy */
7986 	    {
7987 	      memcpy (out_data, stripe_data, useful_bytes);
7988 	    }
7989 	} /* end if AV_TRUECOLOR* */
7990 
7991       /* FURTHER POST-PROCESSING ON THE FINAL OUTPUT DATA */
7992 
7993       /* maybe mirroring in ADF mode */
7994       if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_adf_need_mirror)
7995         {
7996 	  if ( (s->c_mode != AV_TRUECOLOR) ||
7997 	       (s->c_mode == AV_TRUECOLOR && dev->inquiry_adf_bgr_order) )
7998 	  {
7999 	    /* Mirroring with bgr -> rgb conversion: Just mirror the
8000 	     * whole line */
8001 
8002 	    unsigned int l;
8003 	    unsigned int lines = useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
8004 
8005 	    for (l = 0; l < lines; ++l)
8006 	      {
8007 		uint8_t* begin_ptr = out_data + (l * (unsigned int) s->avdimen.hw_bytes_per_line);
8008 		uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line;
8009 
8010 		while (begin_ptr < end_ptr) {
8011 		  uint8_t tmp;
8012 		  tmp = *begin_ptr;
8013 		  *begin_ptr++ = *end_ptr;
8014 		  *end_ptr-- = tmp;
8015 		}
8016 	      }
8017 	  }
8018 	else /* non trivial mirroring */
8019 	  {
8020 	    /* Non-trivial Mirroring with element swapping */
8021 
8022 	    unsigned int l;
8023 	    unsigned int lines = useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
8024 
8025 	    for (l = 0; l < lines; ++l)
8026 	      {
8027 		uint8_t* begin_ptr = out_data + (l * (unsigned int) s->avdimen.hw_bytes_per_line);
8028 		uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line - 3;
8029 
8030 		while (begin_ptr < end_ptr) {
8031 		  uint8_t tmp;
8032 
8033 		  /* R */
8034 		  tmp = *begin_ptr;
8035 		  *begin_ptr++ = *end_ptr;
8036 		  *end_ptr++ = tmp;
8037 
8038 		  /* G */
8039 		  tmp = *begin_ptr;
8040 		  *begin_ptr++ = *end_ptr;
8041 		  *end_ptr++ = tmp;
8042 
8043 		  /* B */
8044 		  tmp = *begin_ptr;
8045 		  *begin_ptr++ = *end_ptr;
8046 		  *end_ptr = tmp;
8047 
8048 		  end_ptr -= 5;
8049 		}
8050 	      }
8051 	  }
8052       } /* end if mirroring needed */
8053 
8054       /* byte swapping and software calibration 16bit mode */
8055       if (s->c_mode == AV_GRAYSCALE12 ||
8056           s->c_mode == AV_GRAYSCALE16 ||
8057           s->c_mode == AV_TRUECOLOR12 ||
8058           s->c_mode == AV_TRUECOLOR16) {
8059 
8060 	unsigned int l;
8061 	unsigned int lines = useful_bytes / (unsigned int) s->avdimen.hw_bytes_per_line;
8062 
8063 	uint8_t* dark_avg_data = s->dark_avg_data;
8064 	uint8_t* white_avg_data = s->white_avg_data;
8065 
8066 	uint8_t* begin_ptr = out_data;
8067 	uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line;
8068 	uint8_t* line_ptr;
8069 
8070         double scale = 1.0;
8071         if (s->c_mode == AV_GRAYSCALE12 || s->c_mode == AV_TRUECOLOR12)
8072           scale = (double) (1<<4);
8073 
8074 	while (begin_ptr < end_ptr) {
8075 	  uint16_t dark_avg = 0;
8076 	  uint16_t white_avg = WHITE_MAP_RANGE;
8077 
8078 	  if (dark_avg_data)
8079 	    dark_avg = (uint16_t) get_double_le (dark_avg_data);
8080 	  if (white_avg_data)
8081 	    white_avg = (uint16_t) get_double_le (white_avg_data);
8082 
8083 	  line_ptr = begin_ptr;
8084 	  for (l = 0; l < lines; ++ l)
8085 	    {
8086 	      double v = (double) get_double_le (line_ptr) * scale;
8087 	      uint16_t v2;
8088 	      if (0)
8089 		v = (v - dark_avg) * white_avg / WHITE_MAP_RANGE;
8090 
8091 	      v2 = ((uint16_t) v) < 0xFFFF ? ((uint16_t) v) : 0xFFFF;
8092 
8093 	      /* SANE Standard 3.2.1 "... bytes of each sample value are
8094 		 transmitted in the machine's native byte order." */
8095 	      *line_ptr = (uint8_t) v2;
8096 
8097 	      line_ptr += s->avdimen.hw_bytes_per_line;
8098 	    }
8099 
8100 	  begin_ptr += 2;
8101 	  if (dark_avg_data)
8102 	    dark_avg_data += 2;
8103 	  if (white_avg_data)
8104 	    white_avg_data += 2;
8105 	}
8106       }
8107 
8108       /* SOFTWARE SCALING WITH INTERPOLATION (IF NECESSARY) */
8109 
8110       if (s->avdimen.hw_xres != s->avdimen.xres ||
8111 	  s->avdimen.hw_yres != s->avdimen.yres) /* Software scaling */
8112 	{
8113 	  int x;
8114 	  /* for convenience in the 16bit code path */
8115 	  uint16_t* out_data16 = (uint16_t*) out_data;
8116 
8117 	  const int hw_line_end = hw_line + (int) useful_bytes / s->avdimen.hw_bytes_per_line;
8118 
8119 	  /* on-the-fly bi-linear interpolation */
8120 	  while (1) {
8121 	    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);
8122 	    int sy = (int)floor(by);
8123 	    int ydist = (int) ((by - sy) * 256);
8124 	    int syy = sy + 1;
8125 
8126 	    const int hwbpl = s->avdimen.hw_bytes_per_line;
8127 
8128 	    uint8_t* dst = ip_data;
8129 	    uint16_t* dst16 = (uint16_t*) ip_data;
8130 	    unsigned int v; /* accumulator */
8131 
8132 	    /* Break out if we do not have the hw source line - yet,
8133 	       or when we are past the end of wanted data */
8134 	    if (deinterlace != NONE && !s->duplex_rear_valid && syy >= s->avdimen.hw_lines) {
8135 	      DBG (7, "reader_process: skip due past intended front page lines: %d\n", sy);
8136 	      break;
8137 	    }
8138 	    if (sy >= hw_line_end || syy >= hw_line_end) {
8139 	      DBG (3, "reader_process: source line %d-%d not yet avail\n",
8140 		   sy, syy);
8141 	      break;
8142 	    }
8143 
8144 	    DBG (8, "reader_process: out line: %d <- from: %d-%d\n",
8145 		 line, sy, syy);
8146 
8147 	    /* convert to offset in current stripe */
8148 	    sy -= hw_line;
8149 	    syy -= hw_line;
8150 
8151 	    if (sy < -1) {
8152 	      DBG (1, "reader_process: need more history: %d???\n", sy);
8153 	      sy = -1;
8154 	    }
8155 
8156 	    for (x = 0; x < s->params.pixels_per_line; ++x) {
8157 	      const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line;
8158 	      const int sx = (int)floor(bx);
8159 	      const int xdist = (int) ((bx - sx) * 256);
8160 	      const int sxx = sx + 1;
8161 
8162 	      if (x == 0 || x == s->params.pixels_per_line - 1)
8163 		 DBG (8, "reader_process: x: %d <- from: %d-%d\n",
8164 		      x, sx, sxx);
8165 
8166 	      switch (s->c_mode) {
8167 	      case AV_THRESHOLDED:
8168 	      case AV_DITHERED:
8169 		{
8170 		  /* Repeating this over and over again is not fast, but
8171 		     as a seldom used code-path we want it readable.
8172 		     x/8 is the byte, and x%8 the bit position. */
8173 		  v = (unsigned int) (
8174 		    ( ((out_data [sy*hwbpl  + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * (256-ydist) +
8175 		      ((out_data [sy*hwbpl  + sxx/8] >> (7-sxx%8)) & 1) * xdist       * (256-ydist) +
8176 		      ((out_data [syy*hwbpl + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * ydist +
8177 		      ((out_data [syy*hwbpl + sxx/8] >> (7-sxx%8)) & 1) * xdist       * ydist
8178 		      ) / (1 + 1 * 256));
8179 
8180 		  /* Shift and or the result together and eventually
8181 		     jump to the next byte. */
8182 		  *dst = (uint8_t) ((*dst << 1) | ((v>>7)&1));
8183 		    if (x % 8 == 7)
8184 		     ++dst;
8185 		}
8186 		break;
8187 
8188 	      case AV_GRAYSCALE:
8189 		{
8190 		  v = (unsigned int) (
8191 		    ( out_data [sy*hwbpl  + sx ] * (256-xdist) * (256-ydist) +
8192 		      out_data [sy*hwbpl  + sxx] * xdist       * (256-ydist) +
8193 		      out_data [syy*hwbpl + sx ] * (256-xdist) * ydist +
8194 		      out_data [syy*hwbpl + sxx] * xdist       * ydist
8195 		      ) / (256 * 256));
8196 		  *dst++ = (uint8_t) v;
8197 		}
8198 		break;
8199 
8200 	      case AV_GRAYSCALE12:
8201 	      case AV_GRAYSCALE16:
8202 		{
8203 		  /* TODO: test! */
8204 		  v = (unsigned int) (
8205 		    ( out_data16 [sy*hwbpl  + sx ] * (256-xdist) * (256-ydist) +
8206 		      out_data16 [sy*hwbpl  + sxx] * xdist       * (256-ydist) +
8207 		      out_data16 [syy*hwbpl + sx ] * (256-xdist) * ydist +
8208 		      out_data16 [syy*hwbpl + sxx] * xdist       * ydist
8209 		      ) / (256 * 256));
8210 		  *dst16++ = (uint16_t) v;
8211 		}
8212 		break;
8213 
8214 	      case AV_TRUECOLOR:
8215 		{
8216 		  int c;
8217 		  for (c = 0; c < 3; ++c)
8218 		    {
8219 		      v = (unsigned int) (
8220 			( out_data [sy*hwbpl  + sx*3  + c] * (256-xdist) * (256-ydist) +
8221 			  out_data [sy*hwbpl  + sxx*3 + c] * xdist       * (256-ydist) +
8222 			  out_data [syy*hwbpl + sx*3  + c] * (256-xdist) * ydist +
8223 			  out_data [syy*hwbpl + sxx*3 + c] * xdist       * ydist
8224 			  ) / (256 * 256));
8225 		      *dst++ = (uint8_t) v;
8226 		    }
8227 		}
8228 		break;
8229 
8230 	      case AV_TRUECOLOR12:
8231 	      case AV_TRUECOLOR16:
8232 		{
8233 		  /* TODO: test! */
8234 		  int c;
8235 		  for (c = 0; c < 3; ++c)
8236 		    {
8237 		      v = (unsigned int) (
8238 			( out_data16 [sy*hwbpl  + sx*3  + c] * (256-xdist) * (256-ydist) +
8239 			  out_data16 [sy*hwbpl  + sxx*3 + c] * xdist       * (256-ydist) +
8240 			  out_data16 [syy*hwbpl + sx*3  + c] * (256-xdist) * ydist +
8241 			  out_data16 [syy*hwbpl + sxx*3 + c] * xdist       * ydist
8242 			  ) / (256 * 256));
8243 		      *dst16++ = (uint16_t) v;
8244 		    }
8245 		}
8246 		break;
8247 
8248 	      case AV_COLOR_MODE_LAST:
8249 		; /* silence compiler warning */
8250 	      }
8251 	    }
8252 	    fwrite (ip_data, (size_t) s->params.bytes_per_line, 1, fp);
8253 	    ++line;
8254 	  }
8255 	  /* copy one line of history for the next pass */
8256 	  memcpy (ip_history,
8257 	          out_data + useful_bytes - s->avdimen.hw_bytes_per_line,
8258 		  (size_t) s->avdimen.hw_bytes_per_line);
8259 	}
8260       else /* No scaling */
8261 	{
8262           fwrite (out_data, useful_bytes, 1, fp);
8263           line += (int) useful_bytes / s->avdimen.hw_bytes_per_line;
8264 	}
8265       }
8266 
8267       /* save image date in stripe buffer for next next stripe */
8268       stripe_fill -= useful_bytes;
8269       if (stripe_fill > 0)
8270 	memcpy (stripe_data, stripe_data + useful_bytes, stripe_fill);
8271 
8272       hw_line += (int) useful_bytes / s->avdimen.hw_bytes_per_line;
8273 
8274       DBG (3, "reader_process: end of iteration\n");
8275     } /* end while not all lines or inf. mode */
8276 
8277   DBG (3, "reader_process: i/o loop finished\n");
8278   if (exit_status == SANE_STATUS_GOOD)
8279     exit_status = SANE_STATUS_EOF;
8280 
8281   if (raw_fp)
8282     fclose (raw_fp);
8283 
8284   /* maybe we need to fill in some white data */
8285   if (exit_status == SANE_STATUS_EOF && line < s->params.lines) {
8286     DBG (3, "reader_process: padding with white data\n");
8287     memset (out_data, gray_mode ? 0xff : 0x00, (size_t) s->params.bytes_per_line);
8288 
8289     DBG (6, "reader_process: padding line %d - %d\n",
8290 	 line, s->params.lines);
8291     while (line < s->params.lines) {
8292       fwrite (out_data, (size_t) s->params.bytes_per_line, 1, fp);
8293       ++line;
8294     }
8295   }
8296 
8297   /* ADF offset compensation */
8298   if (dev->adf_offset_compensation) {
8299 
8300     long lines;
8301     uint8_t* buffer;
8302 
8303     buffer = malloc ((size_t) s->params.bytes_per_line);
8304     lines = ftell(fp) / s->params.bytes_per_line;
8305     rewind(fp);
8306 
8307     for (long line = 0; line < lines; line++) {
8308       fread(buffer, (size_t) s->params.bytes_per_line, 1, fp);
8309 
8310       if ( (!s->duplex_rear_valid && (line < s->avdimen.offset.front.top)) ||
8311            (s->duplex_rear_valid && (line < s->avdimen.offset.rear.top)) ) {
8312         DBG (7, "reader_process: skip due read offset line: %ld\n", line);
8313         continue;
8314       }
8315 
8316       if ( (!s->duplex_rear_valid && (line > (lines - s->avdimen.offset.front.bottom))) ||
8317            (s->duplex_rear_valid && (line > (lines - s->avdimen.offset.rear.bottom))) ) {
8318         DBG (7, "reader_process: skip due read offset line: %ld to %ld\n", line, lines);
8319         break; /* nothing more to write, so break out here */
8320       }
8321 
8322       fwrite(buffer, (size_t) s->params.bytes_per_line, 1, fp_fd);
8323     }
8324   }
8325 
8326   /* Eject film holder and/or release_unit - but only for
8327      non-duplex-rear / non-virtual scans. */
8328   if ((deinterlace != NONE && s->duplex_rear_valid) ||
8329      ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && s->duplex_rear_valid))
8330     {
8331       DBG (1, "reader_process: virtual duplex scan - no device cleanup!\n");
8332     }
8333   else
8334     {
8335       /* poll the cancel button if the scanner is marked as having one */
8336       if (dev->hw->feature_type & AV_CANCEL_BUTTON) {
8337 	if (get_button_status (s) == SANE_STATUS_CANCELLED)
8338 	  exit_status =  SANE_STATUS_CANCELLED;
8339       }
8340 
8341       if (dev->inquiry_new_protocol && dev->scanner_type == AV_FILM) {
8342 	status = object_position (s, AVISION_SCSI_OP_GO_HOME);
8343 	if (status != SANE_STATUS_GOOD)
8344 	  DBG (1, "reader_process: object position go-home failed!\n");
8345       }
8346 
8347       status = release_unit (s, 0);
8348       if (status != SANE_STATUS_GOOD)
8349 	DBG (1, "reader_process: release_unit failed\n");
8350     }
8351 
8352   if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->page % 2) {
8353     /* front page of flipping duplex */
8354     if (exit_status == SANE_STATUS_EOF) {
8355       if (s->val[OPT_ADF_FLIP].w) {
8356         /* The page flip bit must be reset after every scan, but if the
8357          * user doesn't care, there's no reason to reset.
8358          */
8359         status = set_window (s);
8360         if (status != SANE_STATUS_GOOD) {
8361           DBG (1, "reader_process: set scan window command failed: %s\n",
8362           sane_strstatus (status));
8363           return status;
8364         }
8365       }
8366       /* We run in a separate process or thread.  In the latter case,
8367          any change we make to s before the reader_process invocation
8368          needs to be reverted. */
8369       SANE_Int lines = s->params.lines;
8370       s->page += 1;
8371       s->params.lines = -line;
8372       exit_status = reader_process (s);
8373       s->params.lines = lines;
8374       s->page -= 1;
8375     }
8376     /* TODO:
8377     * else {
8378     *   spit out the page if an error was encountered...
8379     *   assuming the error won't prevent it.
8380     * } */
8381   } else {
8382     fclose (fp);
8383   }
8384   if (rear_fp)
8385     fclose (rear_fp);
8386 
8387   if (fp_fd)
8388     fclose(fp_fd);
8389 
8390   if (ip_data) free (ip_data);
8391   if (ip_history)
8392     free (ip_history);
8393   else
8394     free (out_data); /* if we have ip_history out_data is included there */
8395 
8396   free (stripe_data);
8397 
8398   DBG (3, "reader_process: returning success\n");
8399   return exit_status;
8400 }
8401 
8402 /* SANE callback to attach a SCSI device */
8403 static SANE_Status
attach_one_scsi(const char * dev)8404 attach_one_scsi (const char* dev)
8405 {
8406   attach (dev, AV_SCSI, 0);
8407   return SANE_STATUS_GOOD;
8408 }
8409 
8410 /* SANE callback to attach a USB device */
8411 static SANE_Status
attach_one_usb(const char * dev)8412 attach_one_usb (const char* dev)
8413 {
8414   attach (dev, AV_USB, 0);
8415   return SANE_STATUS_GOOD;
8416 }
8417 
8418 static SANE_Status
sane_reload_devices(void)8419 sane_reload_devices (void)
8420 {
8421   FILE* fp;
8422 
8423   char line[PATH_MAX];
8424   const char* cp = 0;
8425   char* word;
8426   int linenumber = 0;
8427   int model_num = 0;
8428 
8429   sanei_usb_init ();
8430   fp = sanei_config_open (AVISION_CONFIG_FILE);
8431   if (fp <= (FILE*)0)
8432     {
8433       DBG (1, "sane_reload_devices: No config file present!\n");
8434     }
8435   else
8436     {
8437       /* first parse the config file */
8438       while (sanei_config_read  (line, sizeof (line), fp))
8439 	{
8440 	  attaching_hw = 0;
8441 
8442 	  word = NULL;
8443 	  ++ linenumber;
8444 
8445 	  DBG (5, "sane_reload_devices: parsing config line \"%s\"\n",
8446 	       line);
8447 
8448 	  cp = sanei_config_get_string (line, &word);
8449 
8450 	  if (!word || cp == line) {
8451 	    DBG (5, "sane_reload_devices: config file line %d: ignoring empty line\n",
8452 		 linenumber);
8453 	    if (word) {
8454 	      free (word);
8455 	      word = NULL;
8456 	    }
8457 	    continue;
8458 	  }
8459 
8460 	  if (!word) {
8461 	    DBG (1, "sane_reload_devices: config file line %d: could not be parsed\n",
8462 		 linenumber);
8463 	    continue;
8464 	  }
8465 
8466 	  if (word[0] == '#') {
8467 	    DBG (5, "sane_reload_devices: config file line %d: ignoring comment line\n",
8468 		 linenumber);
8469 	    free (word);
8470 	    word = NULL;
8471 	    continue;
8472 	  }
8473 
8474 	  if (strcmp (word, "option") == 0)
8475 	    {
8476 	      free (word);
8477 	      word = NULL;
8478 	      cp = sanei_config_get_string (cp, &word);
8479 
8480 	      if (strcmp (word, "disable-gamma-table") == 0) {
8481 		DBG (3, "sane_reload_devices: config file line %d: disable-gamma-table\n",
8482 		     linenumber);
8483 		disable_gamma_table = SANE_TRUE;
8484 	      }
8485 	      else if (strcmp (word, "disable-calibration") == 0) {
8486 		DBG (3, "sane_reload_devices: config file line %d: disable-calibration\n",
8487 		     linenumber);
8488 		disable_calibration = SANE_TRUE;
8489 	      }
8490 	      else if (strcmp (word, "force-calibration") == 0) {
8491 		DBG (3, "sane_reload_devices: config file line %d: force-calibration\n",
8492 		     linenumber);
8493 		force_calibration = SANE_TRUE;
8494 	      }
8495 	      else if (strcmp (word, "force-a4") == 0) {
8496 		DBG (3, "sane_reload_devices: config file line %d: enabling force-a4\n",
8497 		     linenumber);
8498 		force_a4 = SANE_TRUE;
8499 	      }
8500 	      else if (strcmp (word, "force-a3") == 0) {
8501 		DBG (3, "sane_reload_devices: config file line %d: enabling force-a3\n",
8502 		     linenumber);
8503 		force_a3 = SANE_TRUE;
8504 	      }
8505 	      else if (strcmp (word, "skip-adf") == 0) {
8506 		DBG (3, "sane_reload_devices: config file line %d: enabling skip-adf\n",
8507 		     linenumber);
8508 		skip_adf = SANE_TRUE;
8509 	      }
8510 	      else if (strcmp (word, "static-red-calib") == 0) {
8511 		DBG (3, "sane_reload_devices: config file line %d: static red calibration\n",
8512 		     linenumber);
8513 		static_calib_list [0] = SANE_TRUE;
8514 	      }
8515 	      else if (strcmp (word, "static-green-calib") == 0) {
8516 		DBG (3, "sane_reload_devices: config file line %d: static green calibration\n",
8517 		    linenumber);
8518 		static_calib_list [1] = SANE_TRUE;
8519 	      }
8520 	      else if (strcmp (word, "static-blue-calib") == 0) {
8521 		DBG (3, "sane_reload_devices: config file line %d: static blue calibration\n",
8522 		    linenumber);
8523 		static_calib_list [2] = SANE_TRUE;
8524 	      }
8525 	      else
8526 		DBG (1, "sane_reload_devices: config file line %d: options unknown!\n",
8527 		    linenumber);
8528 	    }
8529 	  else if (strcmp (word, "usb") == 0) {
8530 	    DBG (2, "sane_reload_devices: config file line %d: trying to attach USB:`%s'\n",
8531 		 linenumber, line);
8532 	    /* try to attach USB device */
8533 	    sanei_usb_attach_matching_devices (line, attach_one_usb);
8534 	  }
8535 	  else if (strcmp (word, "scsi") == 0) {
8536 	    DBG (2, "sane_reload_devices: config file line %d: trying to attach SCSI: %s'\n",
8537 		 linenumber, line);
8538 
8539 	    /* the last time I verified (2003-03-18) this function
8540 	       only matches SCSI devices ... */
8541 	    sanei_config_attach_matching_devices (line, attach_one_scsi);
8542 	  }
8543 	  else {
8544 	    DBG (1, "sane_reload_devices: config file line %d: OBSOLETE !! use the scsi keyword!\n",
8545 		linenumber);
8546 	    DBG (1, "sane_reload_devices:   (see man sane-avision for details): trying to attach SCSI: %s'\n",
8547 		line);
8548 
8549 	    /* the last time I verified (2003-03-18) this function
8550 	       only matched SCSI devices ... */
8551 	    sanei_config_attach_matching_devices (line, attach_one_scsi);
8552 	  }
8553 	  free (word);
8554 	  word = NULL;
8555 	} /* end while read */
8556 
8557       fclose (fp);
8558 
8559       if (word)
8560 	free (word);
8561     } /* end if fp */
8562 
8563   /* search for all supported SCSI/USB devices */
8564   while (Avision_Device_List [model_num].scsi_mfg != NULL ||
8565          Avision_Device_List [model_num].real_mfg != NULL)
8566     {
8567       /* also potentially accessed from the attach_* callbacks */
8568       attaching_hw = &(Avision_Device_List [model_num]);
8569 	if (attaching_hw->scsi_mfg != NULL)
8570 	  sanei_scsi_find_devices (attaching_hw->scsi_mfg,
8571 				               attaching_hw->scsi_model, NULL,
8572 				               -1, -1, -1, -1,
8573 				               attach_one_scsi);
8574 
8575 	if (attaching_hw->usb_vendor != 0 && attaching_hw->usb_product != 0 )
8576 	{
8577 	  DBG (1, "sane_reload_devices: Trying to find USB device %.4x %.4x ...\n",
8578 	       attaching_hw->usb_vendor,
8579 	       attaching_hw->usb_product);
8580 
8581 	  /* TODO: check return value */
8582 	  if (sanei_usb_find_devices (attaching_hw->usb_vendor,
8583 				      attaching_hw->usb_product,
8584 				      attach_one_usb) != SANE_STATUS_GOOD) {
8585 	    DBG (1, "sane_reload_devices: error during USB device detection!\n");
8586 	  }
8587 	}
8588       ++ model_num;
8589     } /* end for all devices in supported list */
8590 
8591   attaching_hw = 0;
8592   return SANE_STATUS_GOOD;
8593 }
8594 
8595 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)8596 sane_init (SANE_Int* version_code, SANE_Auth_Callback authorize)
8597 {
8598   (void) authorize; /* silence gcc */
8599 
8600   DBG_INIT();
8601 
8602 #ifdef AVISION_STATIC_DEBUG_LEVEL
8603   DBG_LEVEL = AVISION_STATIC_DEBUG_LEVEL;
8604 #endif
8605 
8606   DBG (3, "sane_init:(Version: %i.%i Build: %i)\n",
8607        SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BACKEND_BUILD);
8608 
8609   /* must come first */
8610   sanei_thread_init ();
8611 
8612   if (version_code)
8613     *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BACKEND_BUILD);
8614 
8615   sane_reload_devices ();
8616 
8617   return SANE_STATUS_GOOD;
8618 }
8619 
8620 void
sane_exit(void)8621 sane_exit (void)
8622 {
8623   Avision_Device* dev;
8624   Avision_Device* next;
8625 
8626   DBG (3, "sane_exit:\n");
8627 
8628   for (dev = first_dev; dev; dev = next) {
8629     next = dev->next;
8630     /* no warning for stripping const - C lacks a const_cast<> */
8631     free ((void*)(size_t) dev->sane.name);
8632 
8633     free (dev);
8634   }
8635   first_dev = NULL;
8636 
8637   free(devlist);
8638   devlist = NULL;
8639 }
8640 
8641 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)8642 sane_get_devices (const SANE_Device*** device_list, SANE_Bool local_only)
8643 {
8644   Avision_Device* dev;
8645   unsigned int i;
8646 
8647   (void) local_only; /* silence gcc */
8648 
8649   DBG (3, "sane_get_devices:\n");
8650 
8651   sane_reload_devices ();
8652 
8653   if (devlist)
8654     free (devlist);
8655 
8656   devlist = malloc ((num_devices + 1) * sizeof (devlist[0]));
8657   if (!devlist)
8658     return SANE_STATUS_NO_MEM;
8659 
8660   i = 0;
8661   for (dev = first_dev; i < num_devices; dev = dev->next)
8662     devlist[i++] = &dev->sane;
8663   devlist[i++] = 0;
8664 
8665   *device_list = devlist;
8666   return SANE_STATUS_GOOD;
8667 }
8668 
8669 SANE_Status
sane_open(SANE_String_Const devicename,SANE_Handle * handle)8670 sane_open (SANE_String_Const devicename, SANE_Handle *handle)
8671 {
8672   Avision_Device* dev;
8673   SANE_Status status;
8674   Avision_Scanner* s;
8675   int i, j;
8676   uint8_t inquiry_result[AVISION_INQUIRY_SIZE_V1];
8677 
8678   DBG (3, "sane_open:\n");
8679 
8680   if (devicename[0]) {
8681     for (dev = first_dev; dev; dev = dev->next)
8682       if (strcmp (dev->sane.name, devicename) == 0)
8683 	break;
8684 
8685     if (dev) {
8686       status = attach (devicename, dev->connection.connection_type, &dev);
8687       if (status != SANE_STATUS_GOOD)
8688 	return status;
8689     }
8690   } else {
8691     /* empty devicename -> use first device */
8692     dev = first_dev;
8693   }
8694 
8695   if (!dev)
8696     return SANE_STATUS_INVAL;
8697 
8698   s = malloc (sizeof (*s));
8699   if (!s)
8700     return SANE_STATUS_NO_MEM;
8701 
8702   /* initialize ... */
8703   /* the other states (scanning, ...) rely on this memset (0) */
8704   memset (s, 0, sizeof (*s));
8705 
8706   /* initialize connection state */
8707   s->av_con.connection_type = dev->connection.connection_type;
8708   s->av_con.usb_status = dev->connection.usb_status;
8709   s->av_con.scsi_fd = -1;
8710   s->av_con.usb_dn = -1;
8711 
8712   sanei_thread_initialize (s->reader_pid);
8713   s->read_fds = -1;
8714 
8715   s->hw = dev;
8716 
8717   /* We initialize the table to a gamma value of 2.22, since this is what
8718      papers about Colorimetry suggest.
8719 
8720 	http://www.poynton.com/GammaFAQ.html
8721 
8722      Avision's driver defaults to 2.2 though.
8723 
8724      MN: This is not true for at least Kodak i1120's windows driver.
8725          Some real-world testing showed that a gamma of 1.0 is needed
8726          for this scanner to give decent scan results. Add an option for this...
8727   */
8728 
8729   {
8730     double gamma = 2.22;
8731     if (s->hw->hw->feature_type & AV_GAMMA_10)
8732       gamma = 1.0;
8733     const double one_over_gamma = 1. / gamma;
8734 
8735     for (i = 0; i < 4; ++ i)
8736       for (j = 0; j < 256; ++ j)
8737 	s->gamma_table[i][j] = (SANE_Int) (pow( (double) j / 255, one_over_gamma) * 255);
8738   }
8739 
8740   /* insert newly opened handle into list of open handles: */
8741   s->next = first_handle;
8742   first_handle = s;
8743   *handle = s;
8744 
8745   /* open the device */
8746   if (! avision_is_open (&s->av_con) ) {
8747 #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED
8748     DBG (1, "sane_open: using open_extended\n");
8749     status = avision_open_extended (s->hw->sane.name, &s->av_con, sense_handler, 0,
8750 				    &(dev->scsi_buffer_size));
8751 #else
8752     status = avision_open (s->hw->sane.name, &s->av_con, sense_handler, 0);
8753 #endif
8754     if (status != SANE_STATUS_GOOD) {
8755       DBG (1, "sane_open: open of %s failed: %s\n",
8756 	   s->hw->sane.name, sane_strstatus (status));
8757       return status;
8758     }
8759     DBG (1, "sane_open: got %d scsi_max_request_size\n", dev->scsi_buffer_size);
8760   }
8761 
8762   /* first: re-awake the device with an inquiry, some devices are flunk while initializing
8763      the usb connection and like a inquiry to come first ... (AV610 et.al.) */
8764   status = inquiry (s->av_con, inquiry_result, sizeof(inquiry_result));
8765   if (status != SANE_STATUS_GOOD) {
8766 	DBG (1, "sane_open: awakening inquiry failed: %s\n", sane_strstatus (status));
8767 	return status;
8768   }
8769 
8770   status = wait_ready (&s->av_con, 1);
8771   if (status != SANE_STATUS_GOOD) {
8772     DBG (1, "sane_open: wait_ready() failed: %s\n", sane_strstatus (status));
8773     return status;
8774   }
8775 
8776   /* update settings based on additional accessory information */
8777   status = additional_probe (s);
8778   if (status != SANE_STATUS_GOOD) {
8779     DBG (1, "sane_open: additional probe failed: %s\n", sane_strstatus (status));
8780     return status;
8781   }
8782 
8783   /* initialize the options */
8784   init_options (s);
8785 
8786   if (dev->inquiry_duplex_interlaced &&
8787       (dev->hw->offset.first != 0 ||
8788        dev->hw->offset.front.top != 0 ||
8789        dev->hw->offset.front.bottom != 0 ||
8790        dev->hw->offset.duplex.front.top != 0 ||
8791        dev->hw->offset.duplex.front.bottom != 0 ||
8792        dev->hw->offset.duplex.rear.top != 0 ||
8793        dev->hw->offset.duplex.rear.bottom != 0) )
8794     dev->adf_offset_compensation = SANE_TRUE;
8795 
8796   if (dev->inquiry_duplex_interlaced || dev->scanner_type == AV_FILM ||
8797       dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) {
8798     /* Might need at least *DOS (Windows flavour and OS/2) portability fix
8799        However, I was told Cygwin (et al.) takes care of it. */
8800 
8801     /* Create the file but close the fd. It is not used to open the file later. :( */
8802     strncpy(s->duplex_rear_fname, "/tmp/avision-rear-XXXXXX", PATH_MAX);
8803 
8804     int fd = mkstemp(s->duplex_rear_fname);
8805     if (fd == -1) {
8806       DBG (1, "sane_open: failed to generate temporary fname for duplex scans\n");
8807       return SANE_STATUS_NO_MEM;
8808     }
8809     DBG (1, "sane_open: temporary fname for duplex scans: %s\n", s->duplex_rear_fname);
8810     close(fd);
8811   }
8812 
8813   /* calibrate film scanners, as this must be done without the
8814      film holder and at the full resolution */
8815   if (dev->scanner_type == AV_FILM)
8816     {
8817       int default_res = s->val[OPT_RESOLUTION].w;
8818       s->val[OPT_RESOLUTION].w = dev->inquiry_optical_res;
8819 
8820       DBG (1, "sane_open: early calibration for film scanner.\n");
8821 
8822       compute_parameters (s);
8823 
8824       status = set_window (s);
8825       if (status != SANE_STATUS_GOOD) {
8826 	DBG (1, "sane_open: set scan window command failed: %s\n",
8827 	     sane_strstatus (status));
8828 	return status;
8829       }
8830 
8831       if (!(dev->hw->feature_type & AV_NO_CALIB))
8832 	{
8833 	  status = normal_calibration (s);
8834 	  if (status != SANE_STATUS_GOOD) {
8835 	    DBG (1, "sane_open: perform calibration failed: %s\n",
8836 		 sane_strstatus (status));
8837 	    return status;
8838 	  }
8839 	}
8840 
8841       if (dev->scanner_type == AV_FILM) {
8842 	status = object_position (s, AVISION_SCSI_OP_GO_HOME);
8843 	if (status != SANE_STATUS_GOOD)
8844 	  DBG (1, "reader_open: object position go-home failed!\n");
8845       }
8846 
8847       s->val[OPT_RESOLUTION].w = default_res;
8848     }
8849 
8850   return SANE_STATUS_GOOD;
8851 }
8852 
8853 void
sane_close(SANE_Handle handle)8854 sane_close (SANE_Handle handle)
8855 {
8856   Avision_Scanner* prev;
8857   Avision_Scanner* s;
8858   int i;
8859 
8860   DBG (3, "sane_close:\n");
8861 
8862   for (prev = 0, s = first_handle; s; prev = s, s = s->next) {
8863     if (s == handle)
8864       break;
8865   }
8866 
8867   /* a handle we know about ? */
8868   if (!s) {
8869     DBG (1, "sane_close: invalid handle %p\n", handle);
8870     return;
8871   }
8872 
8873   if (s->scanning)
8874     do_cancel (handle);
8875 
8876   /* close the device */
8877   if (avision_is_open(&s->av_con)) {
8878     avision_close(&s->av_con);
8879   }
8880 
8881   /* remove handle from list of open handles */
8882   if (prev)
8883     prev->next = s->next;
8884   else
8885     first_handle = s->next;
8886 
8887   for (i = 1; i < NUM_OPTIONS; ++ i) {
8888     if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) {
8889       free (s->val[i].s);
8890     }
8891   }
8892 
8893   if (s->white_avg_data)
8894     free (s->white_avg_data);
8895   if (s->dark_avg_data)
8896     free (s->dark_avg_data);
8897 
8898   if (s->background_raster)
8899     free (s->background_raster);
8900 
8901   if (*(s->duplex_rear_fname)) {
8902     unlink (s->duplex_rear_fname);
8903     *(s->duplex_rear_fname) = 0;
8904   }
8905 
8906   free (handle);
8907 }
8908 
8909 const SANE_Option_Descriptor*
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)8910 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
8911 {
8912   Avision_Scanner* s = handle;
8913 
8914   DBG (3, "sane_get_option_descriptor: %d\n", option);
8915 
8916   if ((unsigned) option >= NUM_OPTIONS)
8917     return 0;
8918   return s->opt + option;
8919 }
8920 
8921 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * val,SANE_Int * info)8922 sane_control_option (SANE_Handle handle, SANE_Int option,
8923 		     SANE_Action action, void* val, SANE_Int* info)
8924 {
8925   Avision_Scanner* s = handle;
8926   Avision_Device* dev = s->hw;
8927   SANE_Status status;
8928   SANE_Word cap;
8929 
8930   DBG (3, "sane_control_option: option=%d, action=%d\n",
8931        (int)option, (int)action);
8932 
8933   DBG (5, "sane_control_option: option=%s, action=%s\n",
8934        s->opt[option].name,
8935        action == SANE_ACTION_GET_VALUE ? "GET" :
8936        (action == SANE_ACTION_SET_VALUE ? "SET" :
8937 	(action == SANE_ACTION_SET_AUTO ? "AUTO" : "UNKNOWN") ) );
8938 
8939   if (info)
8940     *info = 0;
8941 
8942   if (s->scanning)
8943     return SANE_STATUS_DEVICE_BUSY;
8944 
8945   if (option >= NUM_OPTIONS)
8946     return SANE_STATUS_INVAL;
8947 
8948   cap = s->opt[option].cap;
8949 
8950   if (!SANE_OPTION_IS_ACTIVE (cap))
8951     return SANE_STATUS_INVAL;
8952 
8953   if (action == SANE_ACTION_GET_VALUE)
8954     {
8955       switch (option)
8956 	{
8957 	  /* word options: */
8958 	case OPT_PREVIEW:
8959 
8960 	case OPT_RESOLUTION:
8961 	case OPT_SPEED:
8962 	case OPT_TL_X:
8963 	case OPT_TL_Y:
8964 	case OPT_BR_X:
8965 	case OPT_BR_Y:
8966 	case OPT_OVERSCAN_TOP:
8967 	case OPT_OVERSCAN_BOTTOM:
8968 	case OPT_BACKGROUND:
8969 	case OPT_NUM_OPTS:
8970 
8971 	case OPT_BRIGHTNESS:
8972 	case OPT_CONTRAST:
8973 	case OPT_EXPOSURE:
8974 	case OPT_IR:
8975 	case OPT_MULTISAMPLE:
8976 	case OPT_QSCAN:
8977 	case OPT_QCALIB:
8978 	case OPT_PAPERLEN:
8979 	case OPT_ADF_FLIP:
8980 	  *(SANE_Word*) val = s->val[option].w;
8981 	  return SANE_STATUS_GOOD;
8982 
8983 	  /* specially treated word options */
8984 
8985 	case OPT_FRAME:
8986 	  status = get_frame_info (s);
8987 	  *(SANE_Word*) val = s->val[option].w;
8988 	  return status;
8989 
8990 	case OPT_POWER_SAVE_TIME:
8991 	  get_power_save_time (s, &(s->val[option].w));
8992 	  *(SANE_Word*) val = s->val[option].w;
8993 	  return SANE_STATUS_GOOD;
8994 
8995 	  /* word-array options: */
8996 	case OPT_GAMMA_VECTOR:
8997 	case OPT_GAMMA_VECTOR_R:
8998 	case OPT_GAMMA_VECTOR_G:
8999 	case OPT_GAMMA_VECTOR_B:
9000 	  memcpy (val, s->val[option].wa, (size_t) s->opt[option].size);
9001 	  return SANE_STATUS_GOOD;
9002 
9003 	  /* string options: */
9004 	case OPT_MODE:
9005 	case OPT_SOURCE:
9006 	  strcpy (val, s->val[option].s);
9007 	  return SANE_STATUS_GOOD;
9008 
9009 	  /* specially treated string options */
9010 	case OPT_MESSAGE:
9011 	  if (dev->inquiry_button_control || dev->inquiry_buttons)
9012 	    status = get_button_status (s);
9013 
9014 	  strcpy (val, s->val[option].s);
9015 	  s->val[option].s[0] = 0;
9016 	  return SANE_STATUS_GOOD;
9017 
9018 	case OPT_NVRAM:
9019 	  get_and_parse_nvram (s, s->val[option].s, 1024);
9020 
9021 	  strcpy (val, s->val[option].s);
9022 	  return SANE_STATUS_GOOD;
9023 
9024 	  /* Boolean options. */
9025         case OPT_OPTION_ADF:
9026         case OPT_OPTION_LIGHTBOX:
9027           *(SANE_Bool*) val = s->val[option].b;
9028           return SANE_STATUS_GOOD;
9029 
9030 	} /* end switch option */
9031     } /* end if GET_ACTION_GET_VALUE */
9032   else if (action == SANE_ACTION_SET_VALUE)
9033     {
9034       if (!SANE_OPTION_IS_SETTABLE (cap))
9035 	return SANE_STATUS_INVAL;
9036 
9037       status = constrain_value (s, option, val, info);
9038       if (status != SANE_STATUS_GOOD)
9039 	return status;
9040 
9041       switch (option)
9042 	{
9043 	  /* side-effect-free word options: */
9044 	case OPT_SPEED:
9045 	case OPT_PREVIEW:
9046 	case OPT_BRIGHTNESS:
9047 	case OPT_CONTRAST:
9048 	case OPT_EXPOSURE:
9049 	case OPT_IR:
9050 	case OPT_MULTISAMPLE:
9051 	case OPT_QSCAN:
9052 	case OPT_QCALIB:
9053 	case OPT_OVERSCAN_TOP:
9054 	case OPT_OVERSCAN_BOTTOM:
9055 	case OPT_BACKGROUND:
9056 	case OPT_PAPERLEN:
9057 	case OPT_ADF_FLIP:
9058 	  s->val[option].w = *(SANE_Word*) val;
9059 	  return SANE_STATUS_GOOD;
9060 
9061 	  /* side-effect-free word-array options: */
9062 	case OPT_GAMMA_VECTOR:
9063 	case OPT_GAMMA_VECTOR_R:
9064 	case OPT_GAMMA_VECTOR_G:
9065 	case OPT_GAMMA_VECTOR_B:
9066 	  memcpy (s->val[option].wa, val, (size_t) s->opt[option].size);
9067 	  return SANE_STATUS_GOOD;
9068 
9069 	  /* options with side-effects: */
9070 	case OPT_RESOLUTION:
9071 	case OPT_TL_X:
9072 	case OPT_TL_Y:
9073 	case OPT_BR_X:
9074 	case OPT_BR_Y:
9075 
9076 	  s->val[option].w = *(SANE_Word*) val;
9077 
9078 	  if (info)
9079 	    *info |= SANE_INFO_RELOAD_PARAMS;
9080 
9081 	  return SANE_STATUS_GOOD;
9082 
9083 	  /* string options with side-effects: */
9084 	case OPT_SOURCE:
9085 
9086 	  if (s->val[option].s) {
9087 	    free(s->val[option].s);
9088 	  }
9089 	  s->val[option].s = strdup(val);
9090 	  s->source_mode = match_source_mode (dev, s->val[option].s);
9091 	  s->source_mode_dim = match_source_mode_dim (s->source_mode);
9092 
9093 	  /* set side-effects */
9094 	  dev->x_range.max =
9095 	    SANE_FIX ( dev->inquiry_x_ranges[s->source_mode_dim]);
9096 	  dev->y_range.max =
9097 	    SANE_FIX ( dev->inquiry_y_ranges[s->source_mode_dim]);
9098 
9099           if (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX) {
9100             s->opt[OPT_ADF_FLIP].cap &= ~SANE_CAP_INACTIVE;
9101           } else {
9102             s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
9103           }
9104 
9105 	  if (info)
9106 	    *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
9107 
9108 	  return SANE_STATUS_GOOD;
9109 
9110 	case OPT_MODE:
9111 	  {
9112 	    if (s->val[option].s)
9113 	      free (s->val[option].s);
9114 
9115 	    s->val[option].s = strdup (val);
9116 	    s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s);
9117 
9118 	    /* set to mode specific values */
9119 
9120 	    /* the gamma table related */
9121 	    if (!disable_gamma_table)
9122 	      {
9123 		if (color_mode_is_color (s->c_mode) ) {
9124 		  s->opt[OPT_GAMMA_VECTOR].cap   |= SANE_CAP_INACTIVE;
9125 		  s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
9126 		  s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
9127 		  s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
9128 		}
9129 		else /* gray or mono */
9130 		  {
9131 		    s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE;
9132 		    s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
9133 		    s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
9134 		    s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
9135 		  }
9136 	      }
9137 	    if (info)
9138 	      *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS;
9139 	    return SANE_STATUS_GOOD;
9140 	  }
9141 	case OPT_FRAME:
9142 	  {
9143 	    SANE_Word frame = *((SANE_Word  *) val);
9144 
9145 	    status = set_frame (s, frame);
9146 	    if (status == SANE_STATUS_GOOD) {
9147 	      s->val[OPT_FRAME].w = frame;
9148 	      dev->current_frame = frame;
9149 	    }
9150 	    return status;
9151 	  }
9152 	case OPT_POWER_SAVE_TIME:
9153 	  {
9154 	    SANE_Word time = *((SANE_Word  *) val);
9155 
9156 	    status = set_power_save_time (s, time);
9157 	    if (status == SANE_STATUS_GOOD)
9158 	      s->val[OPT_POWER_SAVE_TIME].w = time;
9159 	    return status;
9160 	  }
9161 	} /* end switch option */
9162     }
9163   else if (action == SANE_ACTION_SET_AUTO)
9164     {
9165       if (!SANE_OPTION_IS_SETTABLE (cap))
9166 	return SANE_STATUS_INVAL;
9167 
9168       switch (option)
9169 	{
9170 	case OPT_ADF_FLIP:
9171 	  s->val[option].w = SANE_TRUE;
9172 	  return SANE_STATUS_GOOD;
9173 	} /* end switch option */
9174     } /* end else SET_VALUE */
9175   return SANE_STATUS_INVAL;
9176 }
9177 
9178 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)9179 sane_get_parameters (SANE_Handle handle, SANE_Parameters* params)
9180 {
9181   Avision_Scanner* s = handle;
9182 
9183   DBG (3, "sane_get_parameters:\n");
9184 
9185   /* During an actual scan these parameters will have been computed in
9186      sane_start().  Otherwise, the values must be computed on demand.  The
9187      values cannot be changed during a scan to avoid inconsistency. */
9188   if (!s->scanning)
9189     {
9190       DBG (3, "sane_get_parameters: computing parameters\n");
9191       compute_parameters (s);
9192     }
9193 
9194   if (params) {
9195     *params = s->params;
9196     /* add background raster lines */
9197     params->lines += s->val[OPT_BACKGROUND].w;
9198   }
9199 
9200   return SANE_STATUS_GOOD;
9201 }
9202 
9203 SANE_Status
sane_start(SANE_Handle handle)9204 sane_start (SANE_Handle handle)
9205 {
9206   Avision_Scanner* s = handle;
9207   Avision_Device* dev = s->hw;
9208 
9209   SANE_Status status;
9210   int fds [2];
9211   DBG (1, "sane_start:\n");
9212 
9213   /* Make sure there is no scan running!!! */
9214   if (s->scanning)
9215     return SANE_STATUS_DEVICE_BUSY;
9216 
9217   /* Clear cancellation status */
9218   s->cancelled = SANE_FALSE;
9219 
9220   /* Make sure we have a current parameter set. Some of the
9221      parameters will be overwritten below, but that's OK. */
9222   status = sane_get_parameters (s, &s->params);
9223   if (status != SANE_STATUS_GOOD) {
9224     return status;
9225   }
9226 
9227   /* for non ADF scans (e.g. scanimage --batch-prompt on a Flatbed
9228      scanner) make sure we do not assume it's an ADF scan and
9229      optimize something away*/
9230   if (!is_adf_scan (s))
9231     s->page = 0;
9232 
9233   if (s->page > 0 && s->duplex_rear_valid) {
9234     DBG (1, "sane_start: virtual duplex rear data valid.\n");
9235     goto start_scan_end;
9236   }
9237 
9238   /* Check for paper during ADF scans and for sheetfed scanners. */
9239   if (is_adf_scan (s)) {
9240     status = media_check (s);
9241     if (status != SANE_STATUS_GOOD) {
9242       DBG (1, "sane_start: media_check failed: %s\n",
9243 	   sane_strstatus (status));
9244       return status;
9245     }
9246     else
9247       DBG (1, "sane_start: media_check ok\n");
9248   }
9249 
9250   /* Check the light early, to return to the GUI and notify the user. */
9251   if (s->prepared == SANE_FALSE) {
9252     if (dev->inquiry_light_control) {
9253       status = wait_4_light (s);
9254       if (status != SANE_STATUS_GOOD) {
9255         return status;
9256       }
9257     }
9258   }
9259 
9260   if (s->page > 0 && dev->inquiry_keeps_window) {
9261      DBG (1, "sane_start: Optimized set_window away.\n");
9262   }
9263   else
9264   {
9265     status = set_window (s);
9266     if (status != SANE_STATUS_GOOD) {
9267       DBG (1, "sane_start: set scan window command failed: %s\n",
9268 	   sane_strstatus (status));
9269       goto stop_scanner_and_return;
9270     }
9271     /* Re-check the light, as setting the window may have changed
9272      * which light is to be turned on. */
9273     if (s->prepared == SANE_FALSE && dev->inquiry_light_control) {
9274       status = wait_4_light (s);
9275       if (status != SANE_STATUS_GOOD) {
9276 	return status;
9277       }
9278     }
9279   }
9280 
9281 #ifdef DEBUG_TEST
9282   /* debug window size test ... */
9283   if (dev->inquiry_new_protocol)
9284     {
9285       size_t size = 16;
9286       uint8_t result[16];
9287 
9288       DBG (5, "sane_start: reading scanner window size\n");
9289 
9290       status = simple_read (s, 0x80, 0, &size, result);
9291 
9292       if (status != SANE_STATUS_GOOD) {
9293 	DBG (1, "sane_start: get pixel size command failed: %s\n",
9294 	     sane_strstatus (status));
9295 	goto stop_scanner_and_return;
9296       }
9297       debug_print_raw (5, "sane_start: pixel_size:", result, size);
9298       DBG (5, "sane_start: x-pixels: %d, y-pixels: %d\n",
9299 	   get_quad (&(result[0])), get_quad (&(result[4])));
9300     }
9301 #endif
9302 
9303   /* no calibration for ADF pages */
9304   if (s->page > 0) {
9305     DBG (1, "sane_start: optimized calibration away.\n");
9306     goto calib_end;
9307   }
9308 
9309   /* check whether the user enforces calibration */
9310   if (force_calibration) {
9311     DBG (1, "sane_start: calibration enforced in config!\n");
9312     goto calib;
9313   }
9314 
9315   /* Only perform the calibration for newer scanners - it is not needed
9316      for my Avision AV 630 - and also does not even work ... */
9317   if (!dev->inquiry_new_protocol) {
9318     DBG (1, "sane_start: old protocol no calibration needed!\n");
9319     goto calib_end;
9320   }
9321 
9322   if (!dev->inquiry_needs_calibration) {
9323     DBG (1, "sane_start: due to inquiry no calibration needed!\n");
9324     goto calib_end;
9325   }
9326 
9327   /* calibration allowed for this scanner? */
9328   if (dev->hw->feature_type & AV_NO_CALIB) {
9329     DBG (1, "sane_start: calibration disabled in device list!!\n");
9330     goto calib_end;
9331   }
9332 
9333   /* Not for film scanners, ... */
9334   if (dev->scanner_type == AV_FILM) {
9335     DBG (1, "sane_start: no calibration for film scanner!\n");
9336     goto calib_end;
9337   }
9338 
9339   /* check whether calibration is disabled by the user */
9340   if (disable_calibration) {
9341     DBG (1, "sane_start: calibration disabled in config - skipped!\n");
9342     goto calib_end;
9343   }
9344 
9345   /* R² reminder: We must not skip the calibration for ADF scans, some
9346      scanner (HP 53xx/74xx ASIC series) rely on a calibration data
9347      read (and will hang otherwise) */
9348 
9349  calib:
9350   status = normal_calibration (s);
9351 
9352   if (status != SANE_STATUS_GOOD) {
9353     DBG (1, "sane_start: perform calibration failed: %s\n",
9354 	 sane_strstatus (status));
9355 	goto stop_scanner_and_return;
9356   }
9357 
9358  calib_end:
9359 
9360   if (dev->inquiry_3x3_matrix && dev->inquiry_asic_type >= AV_ASIC_C6 &&
9361       s->page == 0)
9362   {
9363     status = send_3x3_matrix (s);
9364     if (status != SANE_STATUS_GOOD) {
9365       return status;
9366     }
9367   }
9368 
9369   /* check whether gamma-table is disabled by the user? */
9370   if (disable_gamma_table) {
9371     DBG (1, "sane_start: gamma-table disabled in config - skipped!\n");
9372     goto gamma_end;
9373   }
9374 
9375   if (dev->hw->feature_type & AV_NO_GAMMA) {
9376     DBG (1, "sane_start: gamma table skipped due to device-list!!\n");
9377     goto gamma_end;
9378   }
9379 
9380   if (s->page > 0 && dev->inquiry_keeps_gamma)
9381     DBG (1, "sane_start: Optimized send_gamma away.\n");
9382   else
9383   {
9384     status = send_gamma (s);
9385     if (status != SANE_STATUS_GOOD) {
9386       DBG (1, "sane_start: send gamma failed: %s\n",
9387 	   sane_strstatus (status));
9388       goto stop_scanner_and_return;
9389     }
9390   }
9391 
9392  gamma_end:
9393 
9394   if (dev->inquiry_tune_scan_length && is_adf_scan (s)) {
9395     status = send_tune_scan_length (s);
9396     if (status != SANE_STATUS_GOOD) {
9397       DBG (1, "sane_start: tune_scan_length command failed: %s\n",
9398 	   sane_strstatus (status));
9399       goto stop_scanner_and_return;
9400     }
9401   }
9402 
9403   /* if the device supports retrieving background raster data
9404      inquire the data no matter if the user/applications asks for
9405      it in order to use it for bottom padding */
9406   if (s->page == 0 && dev->inquiry_background_raster) {
9407     status = get_background_raster (s);
9408     if (status != SANE_STATUS_GOOD) {
9409       DBG (1, "sane_start: get background raster command failed: %s\n",
9410 	   sane_strstatus (status));
9411       goto stop_scanner_and_return;
9412     }
9413   }
9414 
9415   /* check film holder */
9416   if (dev->scanner_type == AV_FILM && dev->holder_type == 0xff) {
9417     DBG (1, "sane_start: no film holder or APS cassette!\n");
9418 
9419     /* Normally "go_home" is executed from the reader process,
9420        but as it will not start we have to reset things here */
9421     if (dev->inquiry_new_protocol) {
9422       status = object_position (s, AVISION_SCSI_OP_GO_HOME);
9423       if (status != SANE_STATUS_GOOD)
9424 	DBG (1, "sane_start: go home failed: %s\n",
9425 	     sane_strstatus (status));
9426     }
9427     goto stop_scanner_and_return;
9428   }
9429 
9430  start_scan_end:
9431 
9432   s->scanning = SANE_TRUE;
9433   s->page += 1; /* processing next page */
9434 
9435   if (pipe (fds) < 0) {
9436     return SANE_STATUS_IO_ERROR;
9437   }
9438 
9439   s->read_fds = fds[0];
9440   s->write_fds = fds[1];
9441 
9442   /* create reader routine as new process or thread */
9443   DBG (3, "sane_start: starting thread\n");
9444   s->reader_pid = sanei_thread_begin (reader_process, (void *) s);
9445 
9446   if (sanei_thread_is_forked()) {
9447     close (s->write_fds);
9448     s->write_fds = -1;
9449   }
9450 
9451   return SANE_STATUS_GOOD;
9452 
9453  stop_scanner_and_return:
9454 
9455   /* cancel the scan nicely */
9456   do_cancel (s);
9457 
9458   return status;
9459 }
9460 
9461 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * buf,SANE_Int max_len,SANE_Int * len)9462 sane_read (SANE_Handle handle, SANE_Byte* buf, SANE_Int max_len, SANE_Int* len)
9463 {
9464   Avision_Scanner* s = handle;
9465   ssize_t nread;
9466   *len = 0;
9467 
9468   DBG (8, "sane_read: max_len: %d\n", max_len);
9469 
9470   nread = read (s->read_fds, buf, (size_t) max_len);
9471   if (nread > 0) {
9472     DBG (8, "sane_read: got %ld bytes\n", (long) nread);
9473   }
9474   else {
9475     DBG (3, "sane_read: got %ld bytes, err: %d %s\n", (long) nread, errno, strerror(errno));
9476   }
9477 
9478   if (!s->scanning)
9479     return SANE_STATUS_CANCELLED;
9480 
9481   if (nread < 0) {
9482     if (errno == EAGAIN) {
9483       return SANE_STATUS_GOOD;
9484     } else {
9485       do_cancel (s);
9486       return SANE_STATUS_IO_ERROR;
9487     }
9488   }
9489 
9490   *len = (SANE_Int) nread;
9491 
9492   /* if all data was passed through */
9493   if (nread == 0)
9494     return do_eof (s);
9495 
9496   return SANE_STATUS_GOOD;
9497 }
9498 
9499 void
sane_cancel(SANE_Handle handle)9500 sane_cancel (SANE_Handle handle)
9501 {
9502   Avision_Scanner* s = handle;
9503   DBG (3, "sane_cancel:\n");
9504 
9505   /* always do the housekeeping, e.g. flush batch scanner pages */
9506   do_cancel (s);
9507 }
9508 
9509 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)9510 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
9511 {
9512   Avision_Scanner* s = handle;
9513 
9514   DBG (3, "sane_set_io_mode:\n");
9515   if (!s->scanning) {
9516     DBG (3, "sane_set_io_mode: not yet scanning\n");
9517     return SANE_STATUS_INVAL;
9518   }
9519 
9520   if (fcntl (s->read_fds, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0)
9521     return SANE_STATUS_IO_ERROR;
9522 
9523   return SANE_STATUS_GOOD;
9524 }
9525 
9526 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)9527 sane_get_select_fd (SANE_Handle handle, SANE_Int* fd)
9528 {
9529   Avision_Scanner* s = handle;
9530 
9531   DBG (3, "sane_get_select_fd:\n");
9532 
9533   if (!s->scanning) {
9534     DBG (3, "sane_get_select_fd: not yet scanning\n");
9535     return SANE_STATUS_INVAL;
9536   }
9537 
9538   *fd = s->read_fds;
9539   return SANE_STATUS_GOOD;
9540 }
9541