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