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