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